转载请注明出处:http://blog.csdn.net/qq_15650553/article/details/51548025
译者注:第一次做这样的翻译,自己感觉还是很多不足,有些概念没有很好的理解,所以翻译过来的中文可能也会有问题。这篇文章主要是用来记录自己的学习所得。所以网友们若要根据下面的译文来学习,不是不行,但是请谨慎。
这篇文章描述了Android.mk文件的语法,这个文件将Android NDK与你的c/c++代码联系到一起。
Overview
这个Android.mk文件存在于你的project下的jni目录的子目录中,它向编译系统描述了你的源码和共享库。这个文件是GNU makefile的一个小的片段,编译系统会读取它一次或者多次。The Android.mk file is useful for defining project-wide settings that Application.mk, the build system, and your environment variables leave undefined。 It can also override project-wide settings for specific modules.
你可以利用Android.mk的语法将你的源码分为多个module。一个module可以是一个静态库,或者是一个共享库,又或者是一个独立的可执行文件。你可以在每个android.mk文件中定义一个或者多个module,而且你还可以在不同的module中使用相同的源文件。编译系统只会将共享库放到你的应用的包中。另外,静态库是可以生成共享库的。
为了打包这些库,编译系统为你处理了大量的细节。例如,你不必要在android.mk中列出头文件,也不必列出生成的文件之间的明确的依赖关系。NDK编译系统已经为你自动的计算好了这些关系。因此,你应该从未来的支持新的toolchain/platform的NDK版本中获得便利,不用去编辑Android.mk文件。
此android.文件的语法与Android Open Source Project中使用的 Android.mk文件非常接近。While the build system implementation that uses them is different, their similarity is an intentional design decision aimed at making it easier for application developers to reuse source code for external libraries。
Basics
在开始探索Android.mk文件的语法之前,先理解Android.mk的基本组件会非常有用。这章里面使用了Hello-JNI 示例工程里面的Android.mk,并且解释了这个文件中的每一行所扮演的角色。
一个Android.mk文件必须以定义LOCAL_PATH 开始:
LOCAL_PATH := $(call my-dir)
这个变量指示了源码文件在development tree中的位置。这里,my-dir这个宏函数使用编译系统提供的,返回了当前目录的路径(这个目录包含了 Android.mk文件本身)。
接下来的一行定义了CLEAR_VARS 这个变量的是由编译系统提供的。
include $(CLEAR_VARS)
CLEAR_VARS这个变量指向了一个特殊的 GNU Makefile,这个Makefile会为你清除很多类似于LOCAL_XXX 的变量,例如LOCAL_MODULE,LOCAL_SRC_FILES,以及LOCAL_STATIC_LIBRARIES。注意,这里并没有清除LOCAL_PATH。这个变量必须保持它的值因为the system parses all build control files in a single GNU Make execution context where all variables are global。你必须在描述每个module之前都要声明一下这个变量。
然后,LOCAL_MODULE 这个变量用来存你想要编译的module的名字。在你的应用的每个module中都要使用一次这个变量。
LOCAL_MODULE := hello-jni
每个module的名字都必须是唯一的并且不能包含空格。当编译系统生成最终的共享库时,会自动把你赋予LOCAL_MODULE 的值加上前缀和后缀,例如,上面的例子会生成一个名字为libhello-jni.so的库。
注意:如果你的module的名字的前缀已经加上了lib,编译系统就不会再为你加前缀了,它会直接以这个module的名字为共享库的名字,并加上.so的扩展名。所以,假如一个源文件的名字本来就叫libfoo.c,那么产生的共享库的名字就是libfoo.so。这种特性是为了支持 Android platform sources通过Android.mk产生的共享库;像这样的库的名字都会以lib开头。
接下来的一行列出源文件,使用空格隔离不同的源文件:
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES 必须包括你想要包含进module的c/c++的源文件的列表。
最后一行帮助系统把每件事物联系起来。
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY 这个变量指向一个GNU Makefile脚本,这个脚本会收集自你定义的从最近的include之后的每个LOCAL_XXX变量的信息。这个脚本确定了build什么东西,以及怎么build.
这里还有更加复杂的示例代码,在samples 文件夹里面,这些代码都包含有带注释的Android.mk文件。除此以外,Sample: native-activity 提供了很详细的关于 Android.mk 文件的解释。最后,Variables and Macros提供了对这章中的变量的更深入的解释。
Variables and Macros
编译系统提供了很多可以在 Android.mk 里面使用的变量。大部分变量都是预先指定好了值。其他的变量的值你来指定。
除了这些变量以外,你还可以定义自己的变量。如果你打算这样做,记住NDK系统保留了以下变量名:
以LOCAL_开头的名字,例如LOCAL_MODULE。
以PRIVATE_、NDK_或者APP开头的。编译系统在内部使用这些变量名。
小写的变量名,例如my-dir。编译系统同样在内部使用这些变量名。
如果你想要在 Android.mk中定义自己的变量,我们建议你在名字前面加上MY_ 。
NDK定义的变量
这一章我们讨论 GNU Make 变量,这些变量是在编译系统解析Android.mk 文件之前就定义好了的。在某些情况下,NDK会多次解析你的Android.mk文件,每一次使用不同的定义去解析其中一些变量。
CLEAR_VARS
这个变量指向一个构建脚本,这个脚本的作用是清除几乎所有的在上一章提到的LOCAL_XXX 变量。在描述一个新的module之前使用这个变量去引用这个脚本使用它的语法是:
include $(CLEAR_VARS)
BUILD_SHARED_LIBRARY
这个变量指向了一个脚本,这个脚本会收集你在每个module定义的LOCAL_XXX变量信息,而且这个变量还确定了怎样使用你的源码去编译一个共享库。注意,使用这个变量需要你至少已经定义了LOCAL_MODULE 和LOCAL_SRC_FILES。(如需查看更多信息,参考 Module-Description Variables)
使用这个变量的语法如下:
include $(BUILD_SHARED_LIBRARY)
一个这样的变量会使编译系统生成一个以.so结尾的库。
BUILD_STATIC_LIBRARY
这个变量是BUILD_SHARED_LIBRARY 的一个变体,是用来生成一个静态库。构建系统并不会把静态库包含进你的工程里面,但是可以利用静态库生成共享库(参考 LOCAL_STATIC_LIBRARIES 和 LOCAL_WHOLE_STATIC_LIBRARIES,在下面)。这个变量的语法是:
include $(BUILD_STATIC_LIBRARY)
这样的一个变量会使编译系统生成一个以.a结尾的库。
PREBUILT_SHARED_LIBRARY
指向一个脚本,这个脚本被用来指定一个预构建的共享库。与BUILD_SHARED_LIBRARY 和 BUILD_STATIC_LIBRARY 不同,LOCAL_SRC_FILES 的值不能是一个源文件,它必须是一个单独的指向预构建的共享库的路径,例如foo/libfoo.so。使用这个变量的语法是:
include $(PREBUILT_SHARED_LIBRARY)
你也可以在另一个module里面使用LOCAL_PREBUILTS 变量来引用一个预构建的库。更多信息查看 Using Prebuilt Libraries。
PREBUILT_STATIC_LIBRARY
与 PREBUILT_SHARED_LIBRARY 相同,只是指向的一个预构建的静态库。更多信息请见 Using Prebuilt Libraries。
TARGET_ARCH
这个变量是目标CPU架构的名字,就像 Android Open Source Project 里面指定了目标CPU架构。这个变量用于任意的ARM兼容的构建,或者ARM,或者是独立于CPU结构的修订,或者ABI (见下方 TARGET_ARCH_ABI)。
这个变量的值是从你在 Android.mk 文件定义的APP_ABI 中得到的,系统会在解析Android.mk 文件之前读取APP_ABI 。
TARGET_PLATFORM
这个变量代表系统构建的目标Android API 的数字。例如,Android 5.1对应Android API 22:android-22。想要知道完整的系统和api对应的关系,请参考 Android NDK Native APIs。下面的例子展示了如何使用这个变量:
TARGET_PLATFORM := android-22
TARGET_ARCH_ABI
当编译系统解析Android.mk文件的时候,这个变量存储CPU和架构的名字。你可以指定一个或者多个下面列出的名字,使用空格分隔两个名字,Table 1 展示了使用每种CPU和架构时ABI的设置。
Table 1. 对于不用的CPU和架构,ABI的设置。
CPU和架构 | 设置 |
---|---|
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 为目标架构:
TARGET_ARCH_ABI := arm64-v8a
注意: Android NDK 1.6_r1之前这个这个变量被定义为arm。
如需了解更多关于架构ABIs和相关问题,参考 ABI Management;
未来出现的新的架构ABI会有不同的值。
TARGET_ABI
将API的级别和ABI联系在一起,当你在真机上调试系统的时候特别有用。例如,指定一个64位的搭载Android 22的ARM设备:
TARGET_ABI := android-22-arm64-v8a
注意: 直到 Android NDK 1.6_r1,默认的值是android-3-arm。
Module-Description Variables 描述module的变量
这章的这些变量用于描述你的module用于系统构建。每一条module的描述都应遵从以下原则:
- 如需初始化或者去掉与此module相关的变量,使用CLEAR_VARS 。
- 通过给这些变量赋值的方式来描述module。
- 如需设置NDK使用合适的脚本编译module,使用BUILD_XXX 。
LOCAL_PATH
这个变量的作用是给出当前文件的路径。你必须在 Android.mk文件的开头定义它。下面的例子展示了怎样使用:
LOCAL_PATH := $(call my-dir)
指向CLEAR_VARS的脚本不会清除这个变量。因此,即使你的Android.mk文件里面定义了几个module,你仍然只需要定义一次这个变量。
LOCAL_MODULE
这个变量存储你的module的名字。在所有定义的module中这个变量的值必须是唯一的,并且不能包含空格。你必须在包含任何脚本文件之间就要定义它(除了 CLEAR_VARS)。你不必要添加lib前缀或者.so和.a后缀。编译系统会自动添加前缀和后缀。在 Android.mk和Application.mk文件里面都是通过引用module的名字来表示该module的。(Throughout your Android.mk and Application.mk files, refer to your module by its unmodified name)。例如,下面这句会生成一个名为libfoo.so 的共享库module:
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。
注意: 你i无法做到修改文件路径或者后缀名。
LOCAL_SRC_FILES
这个变量包含你想要组成module的源文件的列表。只要列出需要编译器编译的源文件就可以了,编译系统会自动计算出依赖关系。
注意绝对路径和相对路径你都可以使用。
我们建议你避免使用绝对路径,这样可以使你的 Android.mk文件更加轻便。
注意: 在构建文件里面应只使用unix风格 的正斜杠(/)。构建系统不识别Windows风格的反斜杠(\)。
LOCAL_CPP_EXTENSION
你可以使用这个可选的变量来指定你的C++源文件的除了.cpp以外其他的后缀名。例如,下面的例子将后缀名变成了 .cxx (必须包含前面的‘.’):
LOCAL_CPP_EXTENSION := .cxx
自从 NDK r7 以后,你可以使用这个变量指定多个后缀名。例如:
LOCAL_CPP_EXTENSION := .cxx .cpp .cc
LOCAL_CPP_FEATURES
你可以使用这个可选的变量来指明你的代码依赖于特别的C++特性。它会在构建的过程中使用对应的编译器和链接器。这个变量还可以定义那些预构建的二进制文件所依赖的特性,以帮助最后的链接过程变正确。我们建议你使用这个变量而不是使用LOCAL_CPPFLAGS 直接打开frtti 和 fexceptions 特性。使用这个变量可以帮助编译系统为每个module设一个单独的合适的信号值(flags )。使用 LOCAL_CPPFLAGS 会导致编译器为所有的module设置所有的指定的信号值,而不管真正需要的是什么。
例如,指定你的代码使用RTTI(运行时类型信息),写下:
LOCAL_CPP_FEATURES := rtti
指定你的代码使用C++异常:
LOCAL_CPP_FEATURES := exceptions
你也可以指定多个值:
LOCAL_CPP_FEATURES := rtti features
值的先后顺序并不重要。
LOCAL_C_INCLUDES
你可以使用这个变量去指定NDK编译代码(C,C++,汇编)的时候include的路径。例如:
LOCAL_C_INCLUDES := sources/foo
甚至:
LOCAL_C_INCLUDES := $(LOCAL_PATH)//foo
在使用 LOCAL_CFLAGS 和 LOCAL_CPPFLAGS 设置include之前就要定义这个变量。
编译系统还会在使用ndk-gdb调试作原生的调试的时候使用LOCAL_C_INCLUDES 定义的路径。
LOCAL_CFLAGS
这个可选的变量设置编译系统在编译C和C++代码时需要传递的编译器标记(compiler flags)。这个特性在指定额外的宏定义或者编译选项的时候会非常有用。
尽量不要在Android.mk中更改 optimization/debugging 的级别。编译系统会自动根据 Application.mk中的相关信息为你设置这个变量。使用这种方式编译系统会生成在调试时很有用的数据文件。
注意: 在android-ndk-1.5_r1中,这个flag值仅用于c文件中,c++文件不行。现在他们适配了完整的Android构建系统的特性。(你现在可以使用LOCAL_CPPFLAGS 专门设置C++文件的flag)。
通过线面这种方式指定额外的include路径是可能的:
LOCAL_CFLAGS += -I<path>,
相比使用LOCAL_C_INCLUDES ,这样做更好,因为这样的话在使用ndk-gdb调试原生程序的时候也可以使用这些路径。
LOCAL_CPPFLAGS
这个变量是可选的仅用于编译C++源文件的时候需要传递的编译器标记。LOCAL_CPPFLAGS变量会在编译器的命令行中出现,是在LOCAL_CFLAGS 出现之后。
*注意:* 在android-ndk-1.5_r1中,这个变量同时作用于C和C++源文件。如果要为C和C++都指定编译器标记,使用LOCAL_CFLAGS。
LOCAL_STATIC_LIBRARIES
这个变量指定了当前module依赖的静态库。
如果当前的module是共享库或者可执行文件,这个变量会强制让这些库被连接进最后生成的二进制文件中。
如果当前的module是静态库,这个变量仅表示依赖于当前module的其他module也依赖于此变量指定的库。
LOCAL_SHARED_LIBRARIES
这个变量指定了当前module在运行时依赖的共享库。这个变量的信息在链接时是必需的,这个变量会将对应的信息嵌入到最终生成的文件中。
LOCAL_WHOLE_STATIC_LIBRARIES
这个变量是LOCAL_STATIC_LIBRARIES的一个变种,它表示链接器应该将相关联的库认为是 whole archives。获取更多关于whole archives的信息可以查看GNU 链接器的文档,查看 –whole-archive 标记。
当几个静态库中存在循环的依赖时这个变量非常有用。当你使用这个变量构建一个共享库时,这个变量会强制让编译系统把所有的object文件从静态库中拷贝到最后的库中。然后当你要生成可执行文件时这样做就不对了。
LOCAL_LDLIBS
这个变量包含了额外的链接器标记,这些标记在构建你的共享库或者可执行文件时会使用到。这个变量允许你通过以-l为前缀传递你指定的系统中的库的名字。例如,下面的例子告诉链接器生成一个module,这个module在加载的时候链接上了 /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
默认的情况是,编译系统如果在构建一个共享库时发现了一个未定义的引用时会抛出一个未定义错误(undefined symbol error)。这个错误在你寻找bug的时候很有用。
若要关闭这个检查,设置这个变量为true即可。注意这样做可能导致共享库在运行时加载。
注意: 如果你在静态库中定义了这个变量,编译系统会忽略它,并且ndk-build会打印警告。
LOCAL_ARM_MODE
默认地,在thumb 模式下编译系统会生成ARM架构的二进制文件,这种模式下的都是16位的,并且会会链接thumb/目录下的STL 库文件。将这个变量定义为arm 会起强制编译系统以32位的arm模式生成该module的object 文件。下面展示了怎样做:
LOCAL_ARM_MODE := arm
你也可以让编译系统只针对你指定的文件以arm模式编译,你需要在源文件的名字上加上.arm的后缀。例如,下面的例子会告诉编译器总是以arm模式编译bar.c,但是对于foo.c是根据LOCAL_ARM_MODE的值来编译的。
LOCAL_SRC_FILES := foo.c bar.c.arm
注意: 你还可以通过设置 Application.mk中的 APP_OPTIM来实现生成ARM 的二进制文件用来调试。指定debug 会强制以ARM模式构建,因为工具链的调试器不会正确的处理Thumb 模式的代码。
LOCAL_ARM_NEON
这变量仅在指定为armeabi-v7a ABI的时候有用。这个变量允许你在你的C、C++和汇编里面使用ARM 高级SIMD (NEON) GCC本证函数。
要注意并不是所以的ARMv7系列的CPU都支持NEON 指令集扩展。由于这个原因,你必须在运行时检查,以便于安全地运行代码。更多信息查看NEON Support 和The cpufeatures Library。
或者,你还可以通过在源文件的名字后面加上.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 bit 和 The GNU stack kickstart。
LOCAL_DISABLE_RELRO
默认的,NDK利用只读的重定位地址和GOT保护。这个变量使运行时的链接器对重定位后的某些内存区域做出标记作为只读的内存,使得某些安全漏洞更加困难(例如GOT重写)。注意这些保护只在API 16 以后才具有,当API 低于16,这些代码任然会运行,但是没有内存保护。
这个变量默认是打开的,你也可以通过设置这个变量为true的方式关闭。没有一个很好的理由的话我们不建议你这样做。
更多信息查看 RELRO: RELocation Read-Only 和 Security enhancements in RedHat Enterprise Linux (section 6)。
LOCAL_DISABLE_FORMAT_STRING_CHECKS
默认的,编译系统编译时具有字符串保护。这样做会导致一个编译器的错误,如果一个非常量(non-constant )的字符串被用于类似于printf的函数里面。
这个变量默认是打开的,你也可以通过设置这个变量为true的方式关闭。没有一个很好的理由的话我们不建议你这样做。
LOCAL_EXPORT_CFLAGS
这个变量将一系列本module的 C/C++编译标记添加到通过LOCAL_STATIC_LIBRARIES 和 LOCAL_SHARED_LIBRARIES 来引用本module的那些module的LOCAL_CFLAGS 值里面。
例如,观察下面这两个module,foo和bar,bar依赖于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 给编译器。编译系统还会预先将那些你所引用的module的LOCAL_CFLAGS 的值添加到你现在的module的LOCAL_CFLAGS 里面,这样你就可以很简单的重写它们了。
另外,module之间的关系是可传递的,如果zoo 依赖于 bar,bar依赖于foo,那么zoo也会继承从foo那里来的标记。
最后,编译系统在本地编译的时候并没有使用导出的标记(例如编译一个标记被导出的module)。因此,在上面的例子中,编译foo/foo.c的时候并没有向编译器传递-DFOO=1 。如果要本地编译,使用LOCAL_CFLAGS 。
(译者注:此处的本地编译(building locally)的概念不是很清楚)
LOCAL_EXPORT_CPPFLAGS
这个变量和 LOCAL_EXPORT_CFLAGS 是一样的,只是这个变量只适用于C++标记。
LOCAL_EXPORT_C_INCLUDES
这个变量和LOCAL_EXPORT_CFLAGS是一样的,但是用于C的include的路径。例如,当bar.c需要引入foo的头文件时这个变量就很有用。
LOCAL_EXPORT_LDFLAGS
这个和LOCAL_EXPORT_CFLAGS是一样的,只是这个用于链接器标识。
LOCAL_EXPORT_LDLIBS
这个和LOCAL_EXPORT_CFLAGS是一样的,告诉构建系统将指定的系统库的名字传递给编译器。你需要在你指定的库的名字前加上 -l。
注意构建系统会把链接器标识导入到你的module的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,所以它也会依赖于系统的log库。
LOCAL_SHORT_COMMANDS
当你的module里面含有很多源码或者依赖于静态库或共享库的时候将这个变量设置为true。Doing so forces the build system to use @ syntax for archives containing intermediate object files or linking libraries.
这个特性在Windows平台很有用,因为Windows平台的命令行最大包含8191个字符,对于复杂系统显得太小了。 It also impacts the compilation of individual source files, placing nearly all compiler flags inside list files, too.
注意任何不是true的值都会导致变成默认的设置。你也可以在Application.mk文件里面强制规定你的工程的所有的module的行为。
我们不建议默认开启这项特性,因为会让构建系统变得更慢。
LOCAL_THIN_ARCHIVE
当构建静态库的时候设置这个变量为true。这样做会生成一个轻的、小的库文件,这个库文件一般不包含object文件,仅包含指向这些object文件的路径。
这样做对于减小输出文件的大小很有用。这样做的一个缺点是这个样的库文件不能移动到一个其他的位置(因为库文件的里的路径都是相对路径)。
有效的值有,true,false,或者空格。你可以在 Application.mk 的APP_THIN_ARCHIVE上设置一个默认的值。
注意: 在非静态库或者预构建静态库的时候这个变量是被忽略的。
LOCAL_FILTER_ASM
(不是很理解,待翻译)
Define this variable as a shell command that the build system will use to filter the assembly files extracted or generated from the files you specified for LOCAL_SRC_FILES.
Defining this variable causes the following things to occur:
The build system generates a temporary assembly file from any C or C++ source file, instead of compiling them into an object file.
The build system executes the shell command in LOCAL_FILTER_ASM on any temporary assembly file and on any assembly file listed in LOCAL_SRC_FILES, thus generating another temporary assembly file.
The build system compiles these filtered assembly files into an object file.
For example:
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” corresponds to the compiler, “2” to the filter, and “3” to the assembler. The filter must be a standalone shell command that takes the name of the input file as its first argument, and the name of the output file as the second one. For example:
myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S
NDK-provided function macros 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的路径。由于这个原因,你不应该在include其他的文件之后还继续使用my-dir。
例如,思考下面的例子:
LOCAL_PATH := $(call my-dir)
Android.mk
..........declare one module
include $(LOCAL_PATH)/foo/
LOCAL_PATH := $(call my-dir)
..........declare another module
这里的问题在于第二个my-dir的调用将LOCAL_PATH 的值设置为了$PATH/foo
而不是$PATH/foo
,因为$PATH/foo
才是最近include的路径。
你可以在Android.mk文件中加入一些额外的includes来避免这个问题。例如:
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)
Android.mk
LOCAL_PATH := $(MY_LOCAL_PATH)
... declare one module
include $(LOCAL_PATH)/foo/
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
Returns the path of the grandparent makefile in the inclusion tree (the path of the makefile that included the current one).
import-module
这是一个允许你通过module的名字找到并包含这个module的Android.mk文件。典型的应用如下:
$(call import-module,<name>)
在这个例子里面,构建系统会根据NDK_MODULE_PATH这个环境变量所指示的目录里面寻找名为 <name>
的module,然后自动为你include对应的 Android.mk文件。