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 变量指向一个特殊的 GNU Makefile,该文件会为您清除许多 LOCAL_XXX 变量,例如 LOCAL_MODULELOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES。请注意,它不会清除 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 变量指向一个 GNU Makefile 脚本,该脚本收集自最近一次 include 以来在 LOCAL_XXX 变量中定义的所有信息。此脚本确定要构建什么以及如何构建。

示例目录中还有更复杂的示例,其中包含已注释的 Android.mk 文件,可以参考。此外,示例:native-activity 提供了对该示例的 Android.mk 文件的详细说明。最后,变量和宏 提供了有关本节中变量的更多信息。

变量和宏

构建系统提供了许多可用于 Android.mk 文件的变量。其中许多变量都带有预先分配的值。其他一些变量需要您自己分配。

除了这些变量之外,您还可以定义自己的任意变量。如果这样做,请记住 NDK 构建系统保留以下变量名。

  • LOCAL_ 开头的名称,例如 LOCAL_MODULE
  • PRIVATE_NDK_APP 开头的名称。构建系统在内部使用这些名称。
  • 小写名称,例如 my-dir。构建系统也在内部使用这些名称。

如果需要在 Android.mk 文件中定义自己的便利变量,建议在名称前添加 MY_

NDK 定义的包含变量

本节讨论构建系统在解析 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 相同,但用于预构建的静态库。有关使用预构建的更多信息,请参阅 使用预构建库

目标信息变量

构建系统会为 APP_ABI 变量指定的每个 ABI 解析 Android.mk 一次,APP_ABI 通常在您的 Application.mk 文件中定义。如果 APP_ABIall,则构建系统会为 NDK 支持的每个 ABI 解析 Android.mk 一次。本节介绍构建系统每次解析 Android.mk 时定义的变量。

TARGET_ARCH

构建系统在解析此 Android.mk 文件时所针对的 CPU 系列。此变量将是以下之一:armarm64x86x86_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

以下示例显示了如何检查 ARMv8 AArch64 是否是目标 CPU 和 ABI 组合

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

您可以使用此可选变量来指定相对于 NDK root 目录的路径列表,以便在编译所有源代码(C、C++ 和汇编)时将其添加到包含搜索路径中。例如

LOCAL_C_INCLUDES := sources/foo

或者

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

在通过 LOCAL_CFLAGSLOCAL_CPPFLAGS 设置任何相应的包含标志之前,定义此变量。

构建系统还在使用 ndk-gdb 启动原生调试时自动使用 LOCAL_C_INCLUDES 路径。

LOCAL_ASFLAGS

构建 .s.S 文件时传递给 Clang 的标志。

LOCAL_ASMFLAGS

构建 .asm 文件时传递给 yasm 的标志。

LOCAL_CFLAGS

构建 C、C++ 和某些汇编(.s.S,但不包括 .asm)源文件时传递给 Clang 的标志。这种能力对于指定额外的宏定义或编译选项很有用。使用 LOCAL_CPPFLAGS 指定仅适用于 C++ 的标志。使用 LOCAL_CONLYFLAGS 指定仅适用于 C 的标志。

尽量不要在您的 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 之后。使用 LOCAL_CFLAGS 指定适用于 C 和 C++ 的标志。

LOCAL_STATIC_LIBRARIES

此变量存储当前模块依赖的静态库模块列表。

如果当前模块是共享库或可执行文件,则此变量将强制将这些库链接到生成的二进制文件中。

如果当前模块是静态库,则此变量仅表示依赖当前模块的其他模块也将依赖于列出的库。

LOCAL_SHARED_LIBRARIES

此变量是此模块在运行时依赖的共享库模块列表。此信息在链接时以及在生成的文件中嵌入相应的必要信息。

LOCAL_WHOLE_STATIC_LIBRARIES

此变量是 LOCAL_STATIC_LIBRARIES 的变体,并表示链接器应将关联的库模块视为完整档案。有关完整档案的更多信息,请参阅 GNU ld 文档 中有关 --whole-archive 标志的部分。

此变量在多个静态库之间存在循环依赖关系时非常有用。当您使用此变量构建共享库时,它将强制构建系统将所有对象文件从您的静态库添加到最终的二进制文件中。但是,在生成可执行文件时,情况并非如此。

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

默认情况下,构建系统以拇指模式生成 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 高级 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

此变量记录一组 C/C++ 编译器标志,以添加到通过 LOCAL_STATIC_LIBRARIESLOCAL_SHARED_LIBRARIES 变量使用此模块的任何其他模块的 LOCAL_CFLAGS 定义中。

例如,考虑以下两个模块:foobar,它们依赖于 foo

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 中,以便您可以轻松地覆盖它们。

此外,模块之间的关系是可传递的:如果 zoo 依赖于 bar,而 bar 又依赖于 foo,那么 zoo 也继承了从 foo 导出的所有标志。

最后,构建系统在本地构建时不会使用导出的标志(即,构建导出标志的模块)。因此,在上面的示例中,它不会在构建 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.so 依赖于 foo,所以它也依赖于系统日志记录库。

LOCAL_SHORT_COMMANDS

当您的模块具有非常大量的源文件和/或依赖的静态或共享库时,将此变量设置为 true。这样做会强制构建系统对包含中间对象文件或链接库的档案使用 @ 语法。

此功能在 Windows 上可能很有用,因为 Windows 命令行最多只能接受 8191 个字符,对于复杂的项目来说可能太小了。它还会影响单个源文件的编译,将几乎所有编译器标志放在列表文件中,这也是一种解决方法。

请注意,任何与 true 不同的值都将恢复为默认行为。您也可以在您的 Application.mk 文件中定义 APP_SHORT_COMMANDS 来强制对项目中的所有模块执行此行为。

我们不建议默认情况下启用此功能,因为它会使构建速度变慢。

LOCAL_THIN_ARCHIVE

在构建静态库时,将此变量设置为 true。这样做会生成一个**精简档案**,这是一个库文件,它不包含对象文件,而是只包含指向它通常包含的实际对象的路径。

这有助于减少构建输出的大小。缺点是此类库**不能**移动到其他位置(它们内部的所有路径都是相对的)。

有效值为 truefalse 或空。可以在您的 Application.mk 文件中通过 APP_THIN_ARCHIVE 变量设置默认值。

LOCAL_FILTER_ASM

将此变量定义为一个 shell 命令,构建系统将使用该命令来过滤从您为 LOCAL_SRC_FILES 指定的文件中提取或生成的汇编文件。定义此变量会导致以下情况发生

  1. 构建系统从任何 C 或 C++ 源文件生成一个临时汇编文件,而不是将它们编译成目标文件。
  2. 构建系统在任何临时汇编文件和在 LOCAL_SRC_FILES 中列出的任何汇编文件上执行 LOCAL_FILTER_ASM 中的 shell 命令,从而生成另一个临时汇编文件。
  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" 对应于汇编器。过滤器必须是一个独立的 shell 命令,它以输入文件的名称作为其第一个参数,以输出文件的名称作为第二个参数。例如

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-dir 有助于在 Android.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/foo 而不是 $PATH,因为这是它最近的包含指向的位置。

可以通过将其他包含内容放在 Android.mk 文件中的所有其他内容之后来避免此问题。例如

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 的 makefile 的路径)。

grand-parent-makefile

返回包含树中祖父母 makefile 的路径(包含当前 makefile 的 makefile 的路径)。

import-module

一个函数,允许您通过模块的名称查找并包含模块的 Android.mk 文件。一个典型的例子如下

$(call import-module,<name>)

在此示例中,构建系统在您的 NDK_MODULE_PATH 环境变量引用的目录列表中查找标记为 <name> 的模块,并自动为您包含其 Android.mk 文件。