【译】Android.mk

构建你的项目

NDK的核心用途之一是允许你在应用程序中使用C和C++代码编译成的共享库.

本节介绍如何构建native二进制文件供你的应用程序使用,首先说明Android.mk文件,它定义了各个模块或库的属性.然后解释Application.mk文件,它定义了应用程序中使用的所有模块的属性.下一步告诉你如何使用ndk-build脚本,以及NDK用此脚本构建你的源代码.最后进入NDK的高级应用,讨论如何将NDK合并到自己的工具链中,但是要喜欢使用这种方式而不是使用ndk-build.

Android.mk

On this page

  1. Overview
  2. Basics
  3. Variables and Macros
  4. Module-Description Variables

本页介绍Android.mk文件的语法,以及将C和C++源代码关联到安卓NDK中.

概述


Android.mk文件在你项目的jni/目录下,它向构建系统描述源代码和动态库,它其实是GNU makefile的简化版,用来给构建系统一次或多次分析使用.Application.mk、构建系统、你的环境变量未定义时,Android.mk文件对于定义项目范围的设置非常有用.它还可以重写特定模块的项目范围设置.

Android.mk的语法允许将源代码加入到模块中,模块是静态库、共享库或独立的可执行文件.可以在每个Android.mk文件中定义一个或多个模块您可以在每个Android.mk文件中定义一个或多个模块,并且可以在多个模块中使用相同的源文件.构建系统只将共享库放置到应用程序包中. 另外,静态库可以生成共享库..

除了打包库,构建系统还处理各种其他信息.例如,不需要在Android.mk文件中生成文件间的一些头文件或文件间的明确依赖关系.NDK构建系统自动生成这些关系.因此,您应该能够从未来NDK发行版中获得新的工具链/平台支持,而无需修改Android.mk文件.

Android.mk文件语法非常接近分布在Android Open Source Project中的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_MODULE,LOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES.请注意,它不清除LOCAL_PATH.此变量必须保留值.因为在单一的GNU Make执行上下文中所有变量都是全局变量,系统要用这些变量解析所有的控制构建文件(清理后才能避免相互影响).在声明每个模块之前,必须(重新)声明此变量.

下一步,LOCAL_MODULE变量存储要构建的模块的名称.在应用程序中每个模块使用此变量一次.

LOCAL_MODULE := hello-jni

 

每个模块名称必须是唯一的,并且不包含任何空格.构建系统最终生成共享库文件时,会自动给LOCAL_MODULE的名字添加正确的前缀和后缀.例如,上面的示例最终生成名字为libhello-jni.so的库.

注意: 如果模块的名字已经是lib开始,构建系统不会在生成lib前缀;它将按原样使用模块名称,并添加.so扩展名.因此,调用的源文件(例如libfaac)仍然会生成一个名为libfoo.c动态库文件.这种特性支持Android平台通过Android.mk文件生成的库;所有这些库的名称以lib开始.

下一行说明一个源文件,如果有多个文件用空格隔开:

LOCAL_SRC_FILES := hello-jni.c

 

LOCAL_SRC_FILES变量的值为要构建到模块中的一个或多个C/C ++源文件.

最后一行让系统把所有文件一起打包:

include $(BUILD_SHARED_LIBRARY)

 

BUILD_SHARED_LIBRARY变量指向一个GNU Makefile脚本,它从最新包含的信息中收集在LOCAL_XXX变量中定义的所有信息.这个脚本决定构建什么,以及如何构建.

示例目录中有更复杂的示例,你可以查看示例中Android.mk文件的注释.此外,native-activity示例提供了Android.mk文件的详细说明.最后,变量和宏提供了有关本节中变量的更多信息.

变量和宏


构建系统提供了许多用于可能供Android.mk文件使用的变量.许多这些变量都带有预分配的值.其它的要自己分配.

除了这些变量还可以任意定义自己的变量.如果这样做你不要和系统保留的变量名重复,比如下面这些系统保留的变量名:

  • 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_SHARED_LIBRARY

此变量指向构建脚本,该脚本会收集所有LOCAL_XXX开始的变量名信息,以及确定如何用列出的源文件构建目标动态库.请注意,使用此脚本需要至少已经为LOCAL_MODULELOCAL_SRC_FILES指定了值(有关这些变量的更多信息,请参阅模块变量描述).

使用此变量的语法是:

include $(BUILD_SHARED_LIBRARY)

 

BUILD_SHARED_LIBRARY变量使构建系统生成带有.so扩展名的库文件.

BUILD_STATIC_LIBRARY

BUILD_SHARED_LIBRARY变量表示构建静态库.构建系统不会拷贝静态库到你的项目或者包中,但能使用他们构建成动态库(看下面的LOCAL_STATIC_LIBRARIESLOCAL_WHOLE_STATIC_LIBRARIES变量).使用这个变量的语法如下:

include $(BUILD_STATIC_LIBRARY)

 

BUILD_SHARED_LIBRARY变量使构建系统生成带有.a扩展名的库文件.

PREBUILT_SHARED_LIBRARY

这个变量指向一个构建脚本,用于指向一个预编译动态库.不像BUILD_SHARED_LIBRARYBUILD_STATIC_LIBRARY,这里的值不能是LOCAL_SRC_FILES的源文件.相反,它必须是一个已经构建好的动态库的单一路径,例如foo/libfoo.so.使用此变量的语法是:

include $(PREBUILT_SHARED_LIBRARY)

 

还可以使用LOCAL_PREBUILT变量引用另一个模块中的已构建好的动态库.有关使用已构建的动态库的详细信息,请参阅使用已构建好的动态库.

PREBUILT_STATIC_LIBRARY

PREBUILT_SHARED_LIBRARY一样,使用已构建好的静态库.有关使用已构建好的静态库的详细信息,请参阅使用已构建好的静态库.

TARGET_ARCH

指定Android开源项目的目标CPU结构的名称.对于任何和ARM兼容的构建使用arm,独立于CPU结构修订版或ABI(请参见下面的TARGET_ARCH_ABI).

Android.mk中定义的这个变量的值取自APP_ABI变量,在解析Android.mk文件之前系统会读取该变量的值.

TARGET_PLATFORM

用于构建系统目标的Android API级别号.例如,Android 5.1系统镜像对应于Android API级别22:android-22.有关平台名称和相应的Android系统镜像的完整列表,请参阅Android NDK Native APIs.以下示例说明了使用此变量的语法:

TARGET_PLATFORM := android-22

 

TARGET_ARCH_ABI

此变量存储当构建系统解析Android.mk文件时要定位的CPU和体系结构的名称.可以指定一个或多个以下值,使用空格作为多个目标之间的分隔符.表1显示了用于每个受支持的CPU和架构的ABI设置.

表1. 不同CPU和架构的ABI设置.

CPU and architectureSetting
ARMv5TE armeabi
ARMv7 armeabi-v7a
ARMv8 AArch64 arm64-v8a
i686 x86
x86-64 x86_64
mips32 (r1) mips
mips64 (r6) mips64
All all

以下示例显示如何将ARMv8 AArch64设置为目标CPU以及和ABI组合:

TARGET_ARCH_ABI := arm64-v8a

注意: 在Android NDK 1.6_r1及以下,此变量定义为arm.

有关架构ABI和相关兼容性问题的更多详细信息,请参阅ABI Management.

未来更新的ABI将具有不同的值.

TARGET_ABI

Android API级别和ABI的并置,当想要针对实际设备的特定目标系统镜像进行测试时特别有用.例如,指定在Android API级别22上运行的64位ARM设备:

TARGET_ABI := android-22-arm64-v8a

 

注意: 在Android NDK 1.6_r1及以下,默认值为android-3-arm.

模块变量描述


本节中的变量向构建系统描述了你的模块.每个模块描述应该遵循以下基本流程:

    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"

 

如果希望生成的模块名称是LOCAL_MODULE生成的lib+之外的名称,则可以使用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文件更具有移植性.

注意: 构建文件中始终使用Unix风格的正斜杠(/),构建系统不正确处理Windows样式的反斜杠(\).

LOCAL_CPP_EXTENSION

使用此可选变量来表示C++源文件中除.cpp文件之外的文件扩展名.例如,以下行将扩展名更改为.cxx(设置必须包含点).

LOCAL_CPP_EXTENSION := .cxx

 

从NDKr7开始,您可以使用此变量来指定多个扩展.例如:

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目录的路径列表,以便在编译所有源文件(C,C ++和组件)时添加到搜索路径.例如:

LOCAL_C_INCLUDES := sources/foo

 

甚至:

LOCAL_C_INCLUDES := $(LOCAL_PATH)//foo

 

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

当使用ndk-gdb启动本地调试时,构建系统还会自动使用LOCAL_C_INCLUDES路径.

LOCAL_CFLAGS

当编译C和C++源文件时, 此可选变量用来向构建系统传递编译标志.这样做的作用是用于指定其他宏定义或编译选项.

请不要更改Android.mk文件中的优化/调试级别.构建系统使用Application.mk文件中的相关信息自动处理此设置.这样做在调试期间使构建系统能够生成有用的数据文件使用.

注意: 在android-ndk-1.5_r1中,相应的标志只应用于C源文件,而没有应用于C++. 现在他们与完整的Android构建系统行为相匹配(现在可以使用LOCAL_CPPFLAGS仅为C++源指定标志).

可以写入指定其他包含路径:

LOCAL_CFLAGS += -I<path>,

 

但是最好使用LOCAL_C_INCLUDES,因为这样ndk-gdb进行本机调试时这个路径下的C源代码是可供调试的.

 

LOCAL_CPPFLAGS

一个可选的编译器标志集,仅在构建C++源文件时将被传递使用.它们将出现在编译器命令行上的LOCAL_CFLAGS之后.

注意: 在android-ndk-1.5_r1中,相应的标志应用于C和C++源码文件.这已被更正为匹配整个Android构建系统.要为C和C++源文件指定标志,请使用LOCAL_CFLAGS.

LOCAL_STATIC_LIBRARIES

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

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

如果当前模块是静态库,这个变量仅表示其它模块依赖当前模块以及依赖于其它的一些库.

LOCAL_SHARED_LIBRARIES

此变量是模块在运行时所依赖的共享库模块列表.此信息在链接时是必需的,并且在生成的文件中嵌入相应的信息.

LOCAL_WHOLE_STATIC_LIBRARIES

此变量是LOCAL_STATIC_LIBRARIES的变种,表示链接器将相关库模块视为整个存档.有关整个存档的更多信息,请参阅GNU链接器文档中的--whole-archive标志.

当在多个静态库之间存在相互依赖性时此变量很有用.当您使用此变量来构建共享库时,它将强制构建系统将所有对象文件从静态库添加到最终的二进制文件.然而,当生成可执行文件时就不一样了.

LOCAL_LDLIBS

此变量包含用于构建共享库或可执行文件的其他链接器标志的列表.它允许您使用-l前缀来传递特定系统库的名称.例如,以下示例告诉链接器在加载时生成链接到/system/lib/libz.so的模块:

LOCAL_LDLIBS := -lz

 

系统暴露出来的一些系统库,你可以在NDK的发行版中衔接他们,参阅Android NDK Native APIs.

注意: 如果为静态库定义此变量,构建系统将忽略它,ndk-build会输出警告.

LOCAL_LDFLAGS

构建系统在构建共享库或可执行文件时使用的其他链接器标志列表.例如,以下示例使用ARM/X86 GCC 4.6+上的ld.bfd链接器,其中ld.gold是默认.

LOCAL_LDFLAGS += -fuse-ld=bfd

 

注意: 如果为静态库定义此变量,构建系统将忽略它,ndk-build会输出警告.

LOCAL_ALLOW_UNDEFINED_SYMBOLS

默认情况下,当构建共享库时构建系统遇到未定义的引用时,它将抛出一个未定义的符号错误.这个错误可以帮助你发现源代码中的bug.

要禁用此检查,请将此变量设置为true.请注意,此设置可能会导致在运行时加载共享库.

注意: 如果为静态库定义此变量,构建系统将忽略它,ndk-build会输出警告.

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

 

 

注意: 还可以通过将 Application.mk文件中的APP_OPTIM设置为debug来强制构建系统生成ARM二进制文件.指定debug会强制ARM构建,因为工具链调试器不正确处理Thumb代码.

LOCAL_ARM_NEON

此变量仅在使用armeabi-v7a ABI时才起作用.它允许在C和C++源中使用ARM Advanced SIMD(NEON)GCC内联函数,以及在装配文件中使用NEON指令.

请注意,并非所有基于ARMv7的CPU都支持NEON指令集扩展.因此,必须运行时检测才安全地使用此代码.有关更多信息,请参阅NEON 支持The cpufeatures.

或者,您可以使用.neon后缀来指定构建系统仅使用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_NO_EXECUTE

Android NDK r4增加了对“NX bit”安全功能的支持.默认情况下启用它,但可以通过将此变量设置为true来禁用它.但没有一个好的原因不建议这样做.

此功能不会修改ABI,仅在面向ARMv6+CPU设备的内核上启用.启用此功能的机器代码将在较早的CPU架构的设备上运行.

有关更多信息,请参阅维基百科:Wikipedia: NX bitThe GNU stack kickstart.

LOCAL_DISABLE_RELRO

默认情况下,NDK使用只读重定位和GOT保护编译代码.此变量指示运行时链接器在重定位后将某些内存区域标记为只读,从而使某些安全漏洞(例如GOT复写)更加困难.请注意,这些保护功能仅适用于Android API 16级及更高版本.在较低的API级别,代码将仍然运行,但没有内存保护.

此变量默认情况下处于打开状态,但您可以通过将其值设置为true来禁用此变量.没有一个好的理由我们不建议这样做.

有关更多信息,请参阅RELRO: RELocation Read-OnlyRedHat Enterprise Linux中的安全性增强(第6节).

LOCAL_DISABLE_FORMAT_STRING_CHECKS

默认情况下,构建系统编译代码带有格式字符串保护.如果在printf样式函数中使用非常量格式的字符串,这样做会产生编译错误.

默认情况下启用此保护,但您可以通过将此变量的值设置为true来禁用此保护.没有一个好的理由我们不建议这样做.

LOCAL_EXPORT_CFLAGS

此变量记录一组C/C++编译器标志,这些标志添加到其他模块定义的LOCAL_CFLAGS,并且这些模块使用了LOCAL_STATIC_LIBRARIESLOCAL_SHARED_LIBRARIES变量.

例如,考虑以下模块: 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上很有用,其中命令行最多只接受8191个字符,对于复杂项目来说这可能太小.它也影响单个源文件的编译,几乎所有的编译器标志也放在列表文件中.

注意,除true之外的任何值都将恢复为默认行为.您还可以在Application.mk文件中定义APP_SHORT_COMMANDS,以强制项目中所有模块的此行为.

我们不建议默认启用此功能,因为它使得构建更慢.

LOCAL_THIN_ARCHIVE

在构建静态库时将此变量设置为true.这样做将生成一个简约的归档,一个不包含对象文件的库文件,而只是包含实际对象的文件路径.

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

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

注意:对于非静态库模块或预构建的静态库模块,将忽略此操作.

LOCAL_FILTER_ASM

将此变量定义为shell命令,构建系统将用它来过滤从为LOCAL_SRC_FILES指定的文件中提取或生成的程序集文件.

定义此变量会导致发生以下情况:

    1. 构建系统从C或C++源文件生成临时装配文件,而不是将它们编译到目标文件中.
    2. 构建系统在LOCAL_FILTER_ASM中对任何临时装配文件和LOCAL_SRC_FILES中列出的任何装配文件执行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-dirLOCAL_PATH定义为$PATH/foo而不是$PATH,因为这是指向最近的include的地方.

你可以避免这个问题,通过在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文件.

 

 

 

posted @ 2016-11-13 17:22  oho_yoho  阅读(380)  评论(0编辑  收藏  举报