Android.mk

이 페이지는 ndk-build에서 사용하는 Android.mk 빌드 파일의 구문에 관해 설명합니다.

개요

Android.mk 파일은 프로젝트의 jni/ 디렉터리에 속한 하위 디렉터리에 있으며 빌드 시스템의 소스 및 공유 라이브러리를 설명합니다. 이 파일은 실제로는 빌드 시스템에서 한 번 이상 파싱하는 작은 GNU makefile 프래그먼트입니다. Android.mk 파일은 Application.mk, 빌드 시스템 및 환경 변수가 정의되지 않은 상태로 남겨두는 프로젝트 전반의 설정을 정의하는 데 유용합니다. 또한 특정 모듈의 프로젝트 전체 설정을 재정의할 수도 있습니다.

Android.mk의 구문을 사용하여 소스를 모듈로 그룹화할 수 있습니다. 모듈은 정적 라이브러리, 공유 라이브러리 또는 독립형 실행 파일입니다. 각각의 Android.mk 파일에서 하나 이상의 모듈을 정의할 수 있으며 여러 모듈에서 동일한 소스 파일을 사용할 수 있습니다. 빌드 시스템에서는 공유 라이브러리를 애플리케이션 패키지에 넣을 뿐입니다. 또한 정적 라이브러리는 공유 라이브러리를 생성할 수 있습니다.

라이브러리 패키징 외에도 빌드 시스템에서는 다양한 기타 세부정보를 자동으로 처리합니다. 예를 들어 헤더 파일을 나열하거나 Android.mk 파일에 생성된 파일 간의 종속 항목을 명시할 필요가 없습니다. NDK 빌드 시스템에서 이러한 관계를 자동으로 계산해주기 때문입니다. 결과적으로 Android.mk 파일을 직접 조작하지 않아도 향후 NDK 출시의 새로운 도구 모음/플랫폼 지원을 활용할 수 있습니다.

이 파일의 구문은 전체 Android 오픈소스 프로젝트와 함께 배포되는 Android.mk 파일에 사용되는 구문과 매우 흡사합니다. 이들을 사용하는 빌드 시스템 구현은 서로 다르지만 의도적으로 설계 단계에서 이처럼 유사하게 만든 이유는 애플리케이션 개발자들이 외부 라이브러리용 소스 코드를 더 쉽게 재사용할 수 있도록 하기 위해서입니다.

기초

구문을 자세히 살펴보기 전에 먼저 Android.mk 파일에 포함된 기초 사항부터 이해하는 것이 도움이 됩니다. 이 섹션에서는 그런 목적에 맞춰 Hello-JNI 샘플에 있는 Android.mk 파일을 사용하여 파일에 있는 각 행의 역할을 설명합니다.

Android.mk 파일은 다음과 같이 LOCAL_PATH 변수를 정의하는 것으로 시작해야 합니다.

LOCAL_PATH := $(call my-dir)

이 변수는 개발 트리에 있는 소스 파일의 위치를 나타냅니다. 여기서 빌드 시스템이 제공하는 매크로 함수 my-dir은 현재 디렉터리(Android.mk 파일 자체를 포함한 디렉터리)의 경로를 반환합니다.

그다음 행에서는 빌드 시스템이 제공하는 값을 가진 CLEAR_VARS 변수를 선언합니다.

include $(CLEAR_VARS)

CLEAR_VARS 변수는 LOCAL_MODULE, LOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES와 같은 여러 LOCAL_XXX 변수를 자동으로 삭제하는 특수한 GNU Makefile을 가리킵니다. 참고로, 이 변수가 LOCAL_PATH를 삭제하지는 않습니다. 시스템에서는 모든 변수가 전역 변수인 단일 GNU Make 실행 컨텍스트의 모든 빌드 컨트롤 파일을 파싱하기 때문에 이 변수는 자체 값을 유지해야 합니다. 각 모듈을 설명하기 전에 이 변수를 (재)선언해야 합니다

다음으로 LOCAL_MODULE 변수는 빌드하려는 모듈의 이름을 저장합니다. 애플리케이션에서 모듈당 한 번씩 이 변수를 사용합니다.

LOCAL_MODULE := hello-jni

각 모듈 이름은 고유해야 하며 공백을 포함하면 안 됩니다. 빌드 시스템은 최종 공유 라이브러리 파일을 생성할 때 LOCAL_MODULE에 할당하는 이름에 알맞은 접두사와 접미사를 자동으로 추가합니다. 예를 들어 위에 나와 있는 예대로 실행하면 libhello-jni.so라는 라이브러리가 생성됩니다.

다음 행에는 소스 파일이 열거되며 공백으로 여러 파일을 구분합니다.

LOCAL_SRC_FILES := hello-jni.c

LOCAL_SRC_FILES 변수는 모듈에 빌드할 C 또는 C++ 소스 파일의 목록을 포함해야 합니다.

마지막 행은 시스템이 모든 것을 하나로 연결하는 데 도움이 됩니다.

include $(BUILD_SHARED_LIBRARY)

BUILD_SHARED_LIBRARY 변수는 가장 최근의 include 이후로 LOCAL_XXX 변수에 정의한 모든 정보를 수집하는 GNU Makefile 스크립트를 가리킵니다. 이 스크립트에 따라 빌드할 대상과 그 방법이 결정됩니다.

샘플 디렉터리에는 더 복잡한 예가 있으며 주석 처리된 Android.mk 파일을 살펴볼 수 있습니다. 그 밖에도 샘플: native-activity에 샘플의 Android.mk 파일에 관한 자세한 설명이 나와 있습니다. 마지막으로 변수와 매크로에는 이 섹션에서 소개한 변수들에 관한 추가 정보가 설명되어 있습니다.

변수와 매크로

빌드 시스템은 Android.mk 파일에서 사용할 수 있는 변수를 최대한 많이 제공합니다. 이들 변수에는 대부분 미리 할당된 값이 포함되어 있습니다. 다른 변수는 개발자가 직접 값을 할당합니다.

이러한 변수 외에, 자체적으로 임의의 변수를 정의할 수도 있습니다. 임의의 변수를 정의하는 경우 NDK 빌드 시스템에 다음 변수 이름이 예약되어 있다는 점에 유의하세요.

  • LOCAL_로 시작하는 이름(예: LOCAL_MODULE)
  • PRIVATE_, NDK_ 또는 APP으로 시작하는 이름. 빌드 시스템은 이러한 이름을 내부적으로 사용합니다.
  • 소문자로 된 이름(예: my-dir). 빌드 시스템은 이러한 이름 역시 내부적으로 사용합니다.

Android.mk 파일에 편의상 자체 변수를 정의할 필요가 있다면 이름 앞에 MY_를 추가하는 것이 좋습니다.

NDK에서 정의한 include 변수

이 섹션에서는 빌드 시스템이 Android.mk 파일을 파싱하기 전에 정의하는 GNU Make 변수에 관해 설명합니다. 특정 상황에서는 NDK가 매번 이들 변수 중 일부에 다른 정의를 사용하여 Android.mk 파일을 여러 차례 파싱할 수도 있습니다.

CLEAR_VARS

이 변수는 아래의 '개발자 정의 변수' 섹션에 나오는 거의 모든 LOCAL_XXX 변수의 정의를 해제하는 빌드 스크립트를 가리킵니다. 새 모듈을 설명하기 전에 이 변수를 사용해 이 스크립트를 포함하세요. 변수를 사용하기 위한 구문은 다음과 같습니다.

include $(CLEAR_VARS)

BUILD_EXECUTABLE

이 변수는 LOCAL_XXX 변수에 제공한 모듈의 모든 정보를 수집하는 빌드 스크립트를 가리키고 나열한 소스에서 타겟 실행 파일의 빌드 방법을 결정합니다. 이 스크립트를 사용하려면 최소한 LOCAL_MODULELOCAL_SRC_FILES에 값을 이미 할당한 상태여야 합니다. 이러한 변수에 관한 자세한 내용은 모듈 설명 변수를 참고하세요.

변수를 사용하기 위한 구문은 다음과 같습니다.

include $(BUILD_EXECUTABLE)

BUILD_SHARED_LIBRARY

이 변수는 LOCAL_XXX 변수에서 제공한 모듈의 모든 정보를 수집하는 빌드 스크립트를 가리키고 나열한 소스에서 타겟 공유 라이브러리의 빌드 방법을 결정합니다. 이 스크립트를 사용하려면 최소한 LOCAL_MODULELOCAL_SRC_FILES에 값을 이미 할당한 상태여야 합니다. 이러한 변수에 관한 자세한 내용은 모듈 설명 변수를 참고하세요.

변수를 사용하기 위한 구문은 다음과 같습니다.

include $(BUILD_SHARED_LIBRARY)

공유 라이브러리 변수를 사용하면 빌드 시스템이 .so 확장자를 가진 라이브러리 파일을 생성합니다.

BUILD_STATIC_LIBRARY

정적 라이브러리를 빌드하는 데 사용되는 BUILD_SHARED_LIBRARY의 변형입니다. 빌드 시스템에서 정적 라이브러리를 프로젝트/패키지로 복사하지는 않지만 정적 라이브러리를 사용하여 공유 라이브러리를 빌드할 수 있습니다(아래의 LOCAL_STATIC_LIBRARIESLOCAL_WHOLE_STATIC_LIBRARIES 참조). 변수를 사용하기 위한 구문은 다음과 같습니다.

include $(BUILD_STATIC_LIBRARY)

정적 라이브러리 변수를 사용하면 빌드 시스템이 .a 확장자를 가진 라이브러리를 생성합니다.

PREBUILT_SHARED_LIBRARY

미리 빌드된 공유 라이브러리를 지정하는 데 사용되는 빌드 스크립트를 가리킵니다. BUILD_SHARED_LIBRARYBUILD_STATIC_LIBRARY와 달리 여기서는 LOCAL_SRC_FILES의 값이 소스 파일일 수 없으며, foo/libfoo.so와 같이 미리 빌드된 공유 라이브러리의 단일 경로여야 합니다. 변수를 사용하기 위한 구문은 다음과 같습니다.

include $(PREBUILT_SHARED_LIBRARY)

LOCAL_PREBUILTS 변수를 사용해 다른 모듈에서 미리 빌드된 라이브러리를 참조할 수도 있습니다. 미리 빌드된 라이브러리의 사용에 관한 자세한 내용은 미리 빌드된 라이브러리 사용을 참고하세요.

PREBUILT_STATIC_LIBRARY

PREBUILT_SHARED_LIBRARY와 동일하지만 미리 빌드된 정적 라이브러리용입니다. 미리 빌드된 라이브러리의 사용에 관한 자세한 내용은 미리 빌드된 라이브러리 사용을 참고하세요.

타겟 정보 변수

빌드 시스템에서는 일반적으로 Application.mk 파일에 정의된 APP_ABI 변수로 지정된 ABI마다 Android.mk를 한 번 파싱합니다. APP_ABIall이면 빌드 시스템이 NDK에서 지원하는 ABI마다 Android.mk를 한 번 파싱합니다. 이 섹션에서는 빌드 시스템이 Android.mk를 파싱할 때마다 정의하는 변수를 설명합니다.

TARGET_ARCH

빌드 시스템이 이 Android.mk 파일을 파싱할 때 타겟팅하는 CPU 제품군입니다. 이 변수는 arm, arm64, x86 또는 x86_64 중 하나입니다.

TARGET_PLATFORM

빌드 시스템이 이 Android.mk 파일을 파싱할 때 타겟팅하는 Android API 수준 번호입니다. 예를 들어 Android 5.1 시스템 이미지는 Android API 수준 22(android-22)에 상응합니다. 플랫폼 이름과 그에 상응하는 Android 시스템 이미지의 전체 목록은 네이티브 API를 참고하세요. 다음 예는 이 변수를 사용하는 구문을 보여줍니다.

ifeq ($(TARGET_PLATFORM),android-22)
    # ... do something ...
endif

TARGET_ARCH_ABI

빌드 시스템이 이 Android.mk 파일을 파싱할 때 대상으로 하는 ABI입니다. 표 1에는 지원되는 각각의 CPU와 아키텍처에 사용되는 ABI 설정이 나와 있습니다.

표 1. 다양한 CPU 및 아키텍처를 위한 ABI 설정

CPU와 아키텍처 설정
ARMv7 armeabi-v7a
ARMv8 AArch64 arm64-v8a
i686 x86
x86-64 x86_64

다음 예에서는 타겟 CPU와 ABI 조합으로 ARMv8 AArch64를 확인하는 방법을 보여줍니다.

ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
  # ... do something ...
endif

아키텍처 ABI와 관련 호환성 문제에 관한 자세한 내용은 Android ABI를 참고하세요.

향후 새로운 타겟 ABI에 새로운 값이 포함됩니다.

TARGET_ABI

대상 Android API 수준과 ABI가 연결된 형태입니다. 이 연결은 실제 기기의 특정 타겟 시스템 이미지와 비교해 테스트하고 싶을 때 특히 유용합니다. 예를 들어 Android API 수준 22에서 작동하는 64비트 ARM 기기를 확인하는 방법은 다음과 같습니다.

ifeq ($(TARGET_ABI),android-22-arm64-v8a)
  # ... do something ...
endif

모듈 설명 변수

이 섹션의 변수는 빌드 시스템에 대한 모듈을 설명합니다. 각 모듈 설명은 다음 기본 흐름을 따라야 합니다.

  1. CLEAR_VARS 변수를 사용해 모듈과 관련된 변수를 초기화하거나 정의를 해제합니다.
  2. 모듈 설명에 사용되는 변수에 값을 할당합니다.
  3. BUILD_XXX 변수를 사용하여 모듈에 적합한 빌드 스크립트를 사용하도록 NDK 빌드 시스템을 설정합니다.

LOCAL_PATH

이 변수는 현재 파일의 경로를 제공하는 데 사용됩니다. Android.mk 파일의 시작 부분에 이를 정의해야 합니다. 다음 예에서는 정의하는 방법을 보여줍니다.

LOCAL_PATH := $(call my-dir)

CLEAR_VARS에서 가리키는 스크립트에서는 이 변수를 삭제하지 않습니다. 따라서 Android.mk 파일이 여러 모듈을 설명하더라도 한 번만 정의하면 됩니다.

LOCAL_MODULE

이 변수는 모듈의 이름을 저장합니다. 모든 모듈 이름과 비교해 고유한 이름이어야 하고 공백을 포함하면 안 됩니다. 스크립트를 포함하기 전에 변수를 정의해야 합니다(CLEAR_VARS용 스크립트 제외). lib 접두사 또는 .so.a 파일 확장자를 추가할 필요가 없으며 빌드 시스템에서 자동으로 수정합니다. Android.mkApplication.mk 파일 전체에서는 모듈을 수정되지 않은 이름으로 지칭합니다. 예를 들어 다음 행은 libfoo.so라는 공유 라이브러리 모듈을 생성합니다.

LOCAL_MODULE := "foo"

생성된 모듈의 이름이 lib + LOCAL_MODULE의 값이 아닌 다른 이름이 되도록 하려면 LOCAL_MODULE_FILENAME 변수를 사용하여 생성된 모듈의 이름을 개발자가 선택한 이름으로 대신 지정할 수 있습니다.

LOCAL_MODULE_FILENAME

이 선택적 변수를 사용하면 빌드 시스템에서 생성하는 파일에 기본적으로 사용하는 이름을 재정의할 수 있습니다. 예를 들어 LOCAL_MODULE의 이름이 foo라면 시스템에서 이 변수가 생성한 파일의 이름을 libnewfoo로 지정하도록 강제할 수 있습니다. 다음 예에서는 그 방법을 보여줍니다.

LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo

공유 라이브러리 모듈일 때 이 예와 같이 실행하면 libnewfoo.so라는 파일이 생성됩니다.

LOCAL_SRC_FILES

이 변수는 빌드 시스템에서 모듈을 생성하기 위해 사용하는 소스 파일의 목록을 포함합니다. 빌드 시스템에서는 연결된 종속 항목을 모두 자동으로 계산하므로 빌드 시스템에서 실제로 컴파일러에 전달하는 파일만 표시됩니다. (LOCAL_PATH의) 상대 파일 경로와 절대 파일 경로를 모두 사용할 수 있습니다.

절대 파일 경로는 가급적 사용하지 않는 것이 좋습니다. 상대 경로를 사용하면 Android.mk 파일을 더 쉽게 이동할 수 있습니다.

LOCAL_CPP_EXTENSION

이 선택적 변수를 사용하여 C++ 소스 파일에 .cpp 이외의 파일 확장자를 표시할 수 있습니다. 예를 들어 다음 명령줄은 확장자를 .cxx로 변경합니다. 설정 시 점을 포함해야 합니다.

LOCAL_CPP_EXTENSION := .cxx

이 변수를 사용하여 여러 개의 확장자를 지정할 수 있습니다. 예:

LOCAL_CPP_EXTENSION := .cxx .cpp .cc

LOCAL_CPP_FEATURES

이 선택적 변수를 사용하여 코드가 특정 C++ 기능에 종속됨을 나타낼 수 있습니다. 이렇게 하면 빌드 프로세스 중에 올바른 컴파일러와 링커 플래그를 사용 설정할 수 있습니다. 미리 빌드된 바이너리라면 이 변수는 바이너리가 종속된 기능을 선언하는 역할도 하므로 링크가 최종적으로 올바르게 작동하는지 확인하는 데 도움이 됩니다. LOCAL_CPPFLAGS 정의에서 -frtti-fexceptions를 직접 사용하는 대신 이 변수를 사용하는 것이 좋습니다.

이 변수를 사용하면 빌드 시스템에서 각 모듈에 적합한 플래그를 사용할 수 있습니다. LOCAL_CPPFLAGS를 사용하면 컴파일러가 실제 요구에 상관없이 모든 모듈에 관해 지정된 모든 플래그를 사용하게 됩니다.

예를 들어 코드에서 RTTI(런타임 유형 정보)를 사용한다는 것을 나타내려면 다음과 같이 작성하세요.

LOCAL_CPP_FEATURES := rtti

코드에서 C++ 예외를 사용한다는 것을 나타내려면 다음과 같이 작성하세요.

LOCAL_CPP_FEATURES := exceptions

이 변수에 여러 개의 값을 지정할 수도 있습니다. 예:

LOCAL_CPP_FEATURES := rtti features

값을 설명하는 순서는 중요하지 않습니다.

LOCAL_C_INCLUDES

이 선택적 변수를 사용하여 모든 소스(C, C++ 및 어셈블리)를 컴파일할 때 포함 검색 경로에 추가할 NDK root 디렉터리에 상대적인 경로의 목록을 지정할 수 있습니다. 예:

LOCAL_C_INCLUDES := sources/foo

또는 다음과 같이 할 수도 있습니다.

LOCAL_C_INCLUDES := $(LOCAL_PATH)/<subdirectory>/foo

LOCAL_CFLAGS 또는 LOCAL_CPPFLAGS를 통해 상응하는 포함 플래그를 설정하기 전에 이 변수를 정의합니다.

또한 빌드 시스템은 ndk-gdb로 네이티브 디버깅을 실행할 때 자동으로 LOCAL_C_INCLUDES 경로를 사용합니다.

LOCAL_ASFLAGS

.s 또는 .S 파일을 빌드할 때 Clang에 전달되는 플래그입니다.

LOCAL_ASMFLAGS

.asm 파일을 빌드할 때 yasm에 전달되는 플래그입니다.

LOCAL_CFLAGS

C, C++, 일부 어셈블리(.s.S, .asm 제외) 소스 파일을 빌드할 때 Clang에 전달되는 플래그입니다. 이러한 기능은 매크로 정의 또는 컴파일 옵션을 추가로 지정할 때 유용할 수 있습니다. C++용 플래그만 지정하려면 LOCAL_CPPFLAGS를 사용하세요. C용 플래그만 지정하려면 LOCAL_CONLYFLAGS를 사용하세요.

Android.mk 파일의 최적화/디버깅 수준을 변경하지 마세요. 빌드 시스템이 Application.mk 파일의 관련 정보를 사용하여 이 설정을 자동으로 처리할 수 있습니다. 이러한 식으로 작업하면 빌드 시스템에서 디버깅 중에 사용되는 유용한 데이터 파일을 생성할 수 있습니다.

다음 코드를 작성하여 포함 경로를 추가로 지정할 수 있습니다.

LOCAL_CFLAGS += -I<path>,

하지만 이 목적으로는 LOCAL_C_INCLUDES를 사용하는 것이 더 낫습니다. 그렇게 하면 ndk-gdb를 통한 네이티브 디버깅에 이용할 수 있는 경로를 사용하는 것도 가능하기 때문입니다.

LOCAL_CONLYFLAGS

C 소스를 컴파일할 때 Clang에 전달되는 플래그입니다. LOCAL_CFLAGS와 달리 LOCAL_CONLYFLAGS는 C++ 또는 어셈블리 소스를 컴파일할 때 Clang으로 전달되지 않습니다.

LOCAL_CPPFLAGS

C++ 소스 파일 빌드할 때 전달되는 선택적 컴파일러 플래그 집합입니다. 이러한 플래그는 컴파일러의 명령줄에서 LOCAL_CFLAGS 뒤에 표시됩니다. C와 C++ 모두를 대상으로 플래그를 지정하려면 LOCAL_CFLAGS를 사용하세요.

LOCAL_STATIC_LIBRARIES

이 변수는 현재 모듈이 종속된 정적 라이브러리 모듈의 목록을 저장합니다.

현재 모듈이 공유 라이브러리나 실행 파일인 경우 이 변수는 이러한 라이브러리가 결과 바이너리에 연결되도록 합니다.

현재 모듈이 정적 라이브러리인 경우 이 변수는 단순히 현재 모듈에 종속된 다른 모듈이 목록에 표시된 라이브러리에도 종속된다는 점을 나타냅니다.

LOCAL_SHARED_LIBRARIES

이 변수는 이 모듈이 런타임 시 종속되는 공유 라이브러리 모듈의 목록입니다. 이 정보는 링크 시간에 그리고 생성된 파일에 상응하는 정보를 삽입할 때 필요합니다.

LOCAL_WHOLE_STATIC_LIBRARIES

이 변수는 LOCAL_STATIC_LIBRARIES의 변형으로, 링커가 연관된 라이브러리 모듈을 완전한 아카이브로 취급해야 함을 나타냅니다. 완전한 아카이브에 관한 자세한 내용은 --whole-archive 플래그의 GNU ld 문서를 참조하세요.

이 변수는 여러 정적 라이브러리 사이에 순환적 종속 항목이 있을 때 유용합니다. 이 변수를 사용하여 공유 라이브러리를 빌드하면 빌드 시스템에서 정적 라이브러리의 모든 객체 파일을 최종 바이너리에 추가합니다. 하지만 실행 파일을 생성할 때는 그렇지 않습니다.

LOCAL_LDLIBS

이 변수는 공유 라이브러리나 실행 파일을 빌드할 때 사용할 추가 링커 플래그의 목록을 포함합니다. 이 변수를 사용하면 -l 접두사를 사용해 특정 시스템 라이브러리의 이름을 전달할 수 있습니다. 예를 들어 다음은 링커가 로드 시간에 /system/lib/libz.so에 연결하는 모듈을 생성하도록 하는 코드입니다.

LOCAL_LDLIBS := -lz

이 NDK 출시에서 연결할 수 있는 노출된 시스템 라이브러리 목록은 네이티브 API를 참고하세요.

LOCAL_LDFLAGS

빌드 시스템이 공유 라이브러리나 실행 파일을 빌드할 때 사용할 다른 링커 플래그의 목록입니다. 예를 들어 ARM/X86에서 ld.bfd 링커를 사용하려면 다음과 같이 합니다.

LOCAL_LDFLAGS += -fuse-ld=bfd

LOCAL_ALLOW_UNDEFINED_SYMBOLS

기본적으로 빌드 시스템에서 공유 라이브러리를 빌드하려는 동안 정의되지 않은 참조가 발생하면 정의되지 않은 기호 오류가 발생합니다. 이 오류는 소스 코드의 버그를 포착하는 데 도움이 될 수 있습니다.

이 검사를 사용 중지하려면 이 변수를 true로 설정하세요. 이렇게 설정하면 런타임 시 공유 라이브러리가 로드될 수 있습니다.

LOCAL_ARM_MODE

기본적으로 빌드 시스템은 thumb 모드에서 ARM 타겟 바이너리를 생성합니다. 이 모드에서 각 명령은 16비트 크기이고 thumb/ 디렉터리의 STL 라이브러리와 연결됩니다. 이 변수를 arm으로 정의하면 빌드 시스템이 32비트 arm 모드에서 모듈의 객체 파일을 생성합니다. 다음 예에서는 그 방법을 보여줍니다.

LOCAL_ARM_MODE := arm

소스 파일 이름에 .arm 접미사를 추가하여 arm 모드에서 특정 소스만 빌드하도록 빌드 시스템에 명령할 수도 있습니다. 예를 들어 다음은 빌드 시스템이 항상 ARM 모드에서 bar.c를 컴파일하지만 LOCAL_ARM_MODE의 값에 따라 foo.c를 빌드하도록 합니다.

LOCAL_SRC_FILES := foo.c bar.c.arm

LOCAL_ARM_NEON

이 변수는 armeabi-v7a ABI를 대상으로 할 때만 중요합니다. 이 변수를 사용하면 C 및 C++ 소스의 ARM Advanced SIMD(NEON) 컴파일러 내장 기능뿐 아니라 어셈블리 파일의 NEON 명령을 사용할 수 있습니다.

일부 ARMv7 기반 CPU는 NEON 명령 집합 확장을 지원하지 않습니다. 이런 이유로 런타임 검색을 실행해야 런타임 시 이 코드를 안전하게 사용할 수 있습니다. 자세한 내용은 Neon 지원CPU 기능을 참고하세요.

또는 .neon 접미사를 사용하여 빌드 시스템이 NEON 지원으로 특정 소스 파일만 컴파일하도록 지정할 수 있습니다. 다음 예에서는 빌드 시스템이 thumb 및 neon 지원으로 foo.c를 컴파일하고 thumb 지원으로 bar.c를 컴파일하며 ARM 및 NEON 지원으로 zoo.c를 컴파일합니다.

LOCAL_SRC_FILES = foo.c.neon bar.c zoo.c.arm.neon

두 접미사를 모두 사용하려면 .arm.neon 앞에 사용해야 합니다.

LOCAL_DISABLE_FORMAT_STRING_CHECKS

기본적으로, 빌드 시스템은 형식 문자열 보호와 함께 코드를 컴파일합니다. 그렇게 하면 printf 스타일의 함수에 상수가 아닌 형식 문자열이 사용되었을 때 컴파일러 오류가 발생합니다. 이 보호는 기본적으로 사용 설정되어 있지만 이 변수의 값을 true로 설정하여 사용 중지할 수 있습니다. 불가피한 이유가 없다면 사용 중지하지 않는 것이 좋습니다.

LOCAL_EXPORT_CFLAGS

이 변수는 LOCAL_STATIC_LIBRARIES 또는 LOCAL_SHARED_LIBRARIES 변수를 통해 이 변수를 사용하는 다른 모듈의 LOCAL_CFLAGS 정의에 추가할 C/C++ 컴파일러 플래그의 집합을 기록합니다.

예를 들어 다음과 같이 foo에 종속된 foobar의 모듈 쌍을 생각해 보세요.

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)


include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_CFLAGS := -DBAR=2
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

여기서 빌드 시스템은 bar.c를 빌드할 때 -DFOO=1-DBAR=2 플래그를 컴파일러로 전달합니다. 또한 모듈의 LOCAL_CFLAGS 앞에 내보낸 플래그를 추가하므로 플래그를 손쉽게 재정의할 수 있습니다.

그 밖에도 모듈 간의 관계는 전이적입니다. 즉, zoobar에 종속되면 결과적으로 foo에 종속되며 그러면 zoofoo에서 내보낸 플래그도 모두 상속합니다.

마지막으로 빌드 시스템은 로컬에서 빌드할 때(즉, 내보내는 플래그를 가진 모듈을 빌드할 때) 내보낸 플래그를 사용하지 않습니다. 따라서 위 예에서는 foo/foo.c를 빌드할 때 -DFOO=1을 컴파일러에 전달하지 않습니다. 로컬에서 빌드하려면 대신 LOCAL_CFLAGS를 사용하세요.

LOCAL_EXPORT_CPPFLAGS

이 변수는 LOCAL_EXPORT_CFLAGS와 동일하지만 C++ 플래그에만 적용됩니다.

LOCAL_EXPORT_C_INCLUDES

이 변수는 LOCAL_EXPORT_CFLAGS와 동일하지만 C 포함 경로에 적용됩니다. 예를 들어 bar.c에 모듈 foo의 헤더를 포함할 필요가 있을 때 유용합니다.

LOCAL_EXPORT_LDFLAGS

이 변수는 LOCAL_EXPORT_CFLAGS와 동일하지만 링커 플래그에 적용됩니다.

LOCAL_EXPORT_LDLIBS

이 변수는 LOCAL_EXPORT_CFLAGS와 동일하며 특정 시스템 라이브러리의 이름을 컴파일러에 전달하도록 빌드 시스템에 알립니다. 지정하는 각 라이브러리의 이름 앞에 -l을 추가합니다.

빌드 시스템은 모듈의 LOCAL_LDLIBS 변수 값에 가져온 링커 플래그를 추가합니다. 이는 Unix 링커의 작동 방식 때문입니다.

이 변수는 일반적으로 모듈 foo가 정적 라이브러리이고 시스템 라이브러리에 종속된 코드를 포함할 때 유용합니다. 그러면 LOCAL_EXPORT_LDLIBS를 사용하여 종속 항목을 내보낼 수 있습니다. 예:

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

이 예에서 빌드 시스템은 libbar.so를 빌드할 때 링커 명령어 끝에 -llog를 붙입니다. 이를 통해 libbar.sofoo에 종속되므로 시스템 로깅 라이브러리에도 종속됨을 링커에 알려주는 것입니다.

LOCAL_SHORT_COMMANDS

모듈에 소스 또는 종속된 정적 라이브러리나 공유 라이브러리가 매우 많을 때 이 변수를 true로 설정하세요. 그러면 빌드 시스템에서 중간 객체 파일이나 링크 라이브러리를 포함한 아카이브에 @ 구문을 사용하게 됩니다.

명령줄에 허용되는 최대 문자 수가 8,191자에 불과한 Windows에서 이 기능을 유용하게 사용할 수 있습니다. 복잡한 프로젝트에 사용하기엔 턱없이 모자랄 수 있습니다. 이는 개별 소스 파일의 컴파일에도 영향을 미쳐 거의 모든 컴파일러 플래그를 목록 파일 내에도 넣습니다.

true 이외의 값을 선택하면 기본 동작으로 되돌아갑니다. Application.mk 파일에 APP_SHORT_COMMANDS를 정의하여 프로젝트의 모든 모듈에 이 동작을 강제 적용할 수도 있습니다.

이 기능을 기본적으로 사용 설정하면 빌드 속도가 느려지므로 그렇게 하지 않는 것이 좋습니다.

LOCAL_THIN_ARCHIVE

정적 라이브러리를 빌드할 때 이 변수를 true로 설정하세요. 그러면 객체 파일을 포함하지 않는 대신 일반적으로 포함하게 되는 실제 객체의 파일 경로만 포함하는 라이브러리 파일인 씬 아카이브가 생성됩니다.

이는 빌드 출력 크기를 줄이는 데 유용합니다. 단점은 이와 같은 라이브러리를 다른 위치(라이브러리 내부의 모든 경로는 상대 경로임)로 이동할 수 없다는 점입니다.

유효한 값은 true 또는 false이거나 빈 값입니다. APP_THIN_ARCHIVE 변수를 통해 Application.mk 파일에서 기본값을 설정할 수 있습니다.

LOCAL_FILTER_ASM

LOCAL_SRC_FILES에 지정한 파일에서 추출되거나 생성되는 어셈블리 파일을 필터링하기 위해 빌드 시스템에서 사용할 셸 명령어로 이 변수를 정의합니다. 이 변수를 정의하면 다음과 같이 일이 발생합니다.

  1. 빌드 시스템이 C 또는 C++ 소스 파일을 객체 파일로 컴파일하는 대신 이러한 파일에서 임시 어셈블리 파일을 생성합니다.
  2. 빌드 시스템에서는 임시 어셈블리 파일과 LOCAL_SRC_FILES에 나열된 어셈블리 파일의 LOCAL_FILTER_ASM에서 셸 명령어를 실행하며 따라서 다른 임시 어셈블리 파일을 생성합니다.
  3. 빌드 시스템은 이렇게 필터링된 어셈블리 파일을 객체 파일로 컴파일합니다.

예:

LOCAL_SRC_FILES  := foo.c bar.S
LOCAL_FILTER_ASM :=

foo.c --1--> $OBJS_DIR/foo.S.original --2--> $OBJS_DIR/foo.S --3--> $OBJS_DIR/foo.o
bar.S                                 --2--> $OBJS_DIR/bar.S --3--> $OBJS_DIR/bar.o

'1'은 컴파일러, '2'는 필터, '3'은 어셈블러에 해당합니다. 필터는 입력 파일의 이름을 첫 번째 인수로, 출력 파일의 이름을 두 번째 인수로 취하는 독립 실행형 셸 명령어여야 합니다. 예:

myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S

NDK에서 제공되는 함수 매크로

이 섹션에서는 NDK에서 제공하는 GNU Make 함수 매크로를 설명합니다. $(call <function>)을 사용하여 매크로를 평가해 보세요. 이러한 매크로는 텍스트 정보를 반환합니다.

my-dir

이 매크로는 마지막으로 포함된 makefile의 경로를 반환하는데 그 경로는 일반적으로 현재 Android.mk의 디렉터리입니다. my-dirAndroid.mk 파일의 시작 부분에서 LOCAL_PATH를 정의하는 데 유용합니다. 예:

LOCAL_PATH := $(call my-dir)

GNU Make의 작동 방식으로 인해 이 매크로에서 실제로 반환하는 것은 빌드 시스템이 빌드 스크립트를 파싱할 때 포함한 마지막 makefile의 경로입니다. 이러한 이유로 다른 파일을 포함한 후 my-dir을 호출하면 안 됩니다.

예를 들어 다음 예시를 살펴보세요.

LOCAL_PATH := $(call my-dir)

# ... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

LOCAL_PATH := $(call my-dir)

# ... declare another module

여기서 문제는 my-dir의 두 번째 호출이 LOCAL_PATH$PATH 대신 $PATH/foo로 정의한다는 점입니다. 바로 그곳이 가장 최근의 include가 가리키는 곳이기 때문입니다.

Android.mk 파일의 다른 모든 것 뒤에 include를 추가로 삽입하여 이 문제를 피할 수 있습니다. 예:

LOCAL_PATH := $(call my-dir)

# ... declare one module

LOCAL_PATH := $(call my-dir)

# ... declare another module

# extra includes at the end of the Android.mk file
include $(LOCAL_PATH)/foo/Android.mk

파일의 구조를 이러한 식으로 만들 수 없으면 첫 번째 my-dir 호출의 값을 다른 변수에 저장하세요. 예:

MY_LOCAL_PATH := $(call my-dir)

LOCAL_PATH := $(MY_LOCAL_PATH)

# ... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

LOCAL_PATH := $(MY_LOCAL_PATH)

# ... declare another module

all-subdir-makefiles

현재 my-dir 경로의 모든 하위 디렉터리에 있는 Android.mk 파일의 목록을 반환합니다.

이 함수를 사용하여 빌드 시스템의 깊이 중첩된 소스 디렉터리 계층 구조를 제공할 수 있습니다. 기본적으로 NDK는 Android.mk 파일을 포함한 디렉터리에 있는 파일만 찾습니다.

this-makefile

(빌드 시스템에서 함수를 호출한) 현재 makefile의 경로를 반환합니다.

parent-makefile

포함 트리의 상위 makefile 경로(현재 경로를 포함한 makefile의 경로)를 반환합니다.

grand-parent-makefile

포함 트리의 최상위 makefile 경로(현재 경로를 포함한 makefile의 경로)를 반환합니다.

import-module

모듈 이름으로 모듈의 Android.mk 파일을 찾아서 포함할 수 있는 함수입니다. 일반적인 예는 다음과 같습니다.

$(call import-module,<name>)

이 예에서 빌드 시스템은 NDK_MODULE_PATH 환경 변수가 참조하는 디렉터리의 목록에서 <name> 태그가 지정된 모듈을 찾아 모듈의 Android.mk 파일을 자동으로 포함합니다.