【Android源码 栏目提醒】:网学会员,鉴于大家对Android源码 十分关注,论文会员在此为大家搜集整理了“Android NDK 开发教程五:Android.mk文件 - 其它资料”一文,供大家参考学习!
引 路蜂移动软件手机软件开发,手机地图,Java MEBlackberryAndroidiPhoneWindows PhoneMonoTouch .Net FrameworkA ndroid NDK 开发教程五:
Android.mk文件分类:
Android 教程 2012-05-13 19:18 389人阅读 评论0 收藏 举报androidlibraryincludebuildmodulemakefileNDK项目一个重要组成是它的make 文件 –
android.mk. 下面部分来自网络翻译(省得我再翻译了:-.注:大部分情况只需参考HelloJni 和twoLibs 的
android.mk 文件即可,如果你想搞清楚
android.mk 中定义变量的具体含义,可以参考下面翻译。
Android.mk文件语法详述介绍:————这篇文档是用来描述你的C或C源文件中
Android.mk编译文件的语法的,为了理解她们我们需要您先看完docs/OVERVIEW.html(http://hualang.iteye.com/blog/1135105)文件来了解它的作用概览:————
Android.mk文件是用来描述build system编译系统的,更准确的说:–该文件是一个微型的GNU Makefile片段,将由build system解析一次或者多次。
这样,您就可以尽量减少您声明的变量,并且不要以为在解析过程中没有任何定义。
–这个文件但语法是用来允许你将源文件组织成模块,这个模块中含有:-一个静态库.a文件-一个动态库.so文件只有动态库才会被安装/复制到你的应用程序包,尽管静态库可以被用来生成动态库。
你可以在每个模块中 都定义一个
Android.mk文件,你也可以让多个模块共用一个
Android.mk文件。
–build system可以为你处理许多细节,例如:你不许要在
Android.mk文件中列出头文件或者其他的依赖关系,这些NDK的build system会自动为你计算并处理。
这也意味着,当更新到新版本的NDK的时候,你应该得益于新的toolchain/platform的支持,而无需修改你的
Android.mk文件。
注意:这些语法非常接近于分布在完整的开源的
Android源代码中的
Android.mk文件,尽管是build system实现的,但是它们的用法是不同的。
这样故意设计的决定是为了让应用程序开发者重用“外部”库的源代码更容易。
简单实例:————-再详细讲解语法之前,让我们先看看一个简单的例子”hello JNI”它在apps/hello-jni/project下–’src’目录下用于存放java源文件–‘jni’目录下用于存放本地源文件,例如”jni/hello-jni.c”这个源文件实现了一个简单的共享库shared library:实现了一个本地方法,为VM应用程序返回一个字符串。
–‘jni/
Android.mk’文件描述了如何生成一个共享库,它的内容是:—————–
Android.mk————————LOCAL_PATH : call my-dirinclude CLEAR_VARSLOCAL_MODULE : hello-jniLOCAL_SRC_FILES : hello-jni.cinclude BUILD_SHARED_LIBRARY—————————————————现在,让我们分别解释这几行LOCAL_PATH:call my-dirAndroid.mk文件必须以LOCAL_PATH变量开始,它用于在树中定位文件。
在这个例子中,宏功能’my-dir’是由build system提供的,用于返回当前目录路径(包括
Android.mk文件本身)include CLEAR_VARS 1CLEAR_VARS变量是由build system提供的,并且指明了一个GNU makefile文件,这个功能会清理掉所有以LOCAL_开头的内容(例如LOCAL_MODULELOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES等),除了LOCAL_PATH,这句话是必须的,因为如果所有的变量都是全局变量的话,所有的可控的编译文件都需要在一个单独的GNU中被解析并执行LOCAL_MODULE :hello-jniLOCAL_MODULE变量必须被定义,用来区分
Android.mk中的每一个模块。
文件名必须是唯一的,不能有空格。
注意,这里编译器会为你自动加上一些前缀和后缀,来保证文件是一致的,比如:这里表明一个动态连接库模块被命名为”hello-jni”,但是最后会生成为”libhello-jni.so”文件。
但是在Java中装载这个库的时候还是使用”hello-jni”名称。
当然如果我们使用”IMPORTANT NOTE:”编译系统就不会为你加上前缀,但是为了支持
Android平台
源码中的
Android.mk文件,也同样会生成libhello-jni.so这样的文件。
重要提示:如果你将你的模块命名为’libfoo’,编译系统将不会将前缀’lib’加上去,并且也会生成libfoo.so文件。
LOCAL_SRC_FILES : hello-jni.cLOCAL_SRC_FILES变量被需包括一个C和C源文件的列表,这些会编译并聚合到一个模块中。
注意:这里并不需要你列出头文件和被包含的文件,因为编译系统会自动为你计算相关的属性,源代码中的列表会直接传递给编译器。
C默认文件的扩展名是“.cpp”,我们可以通过定义一个LOCAL_DEFAULT_CPP_EXTENSION变量来定义一个不同的C文件。
不要忘记在初始化前面的“.”点(也就是说”.cpp”可以正常工作,但是cpp不能正常工作)include BUILD_SHARED_LIBRARYBUILD_SHARED_LIBRARY这个变量是由系统提供的,并且指定给GNU Makefile的脚本,它可以收集所有你定义的”include CLEAR_VARS”中以LOCAL_开头的变量,并且决定哪些要被编译,哪些应该做的更加准确。
编译生成的是以”libltmodule_namegt.so”的文件,这个就是共享库了。
我们同样也可以使用BUILD_STATIC_LIBRARY编译系统便会生成一个以”libltmodule_namegt.a”的文件来供动态库调用。
在samples目录下有很多复杂的例子,那里的
Android.mk文件可以供我们参考参考:———————–这是个变量的列表,你可以依赖或者定义它们到
Android.mk中。
你可以定义自己使用的其他变量,但是NDK辨析系统只保留了以下名字:–以LOCAL_开头的名称(如:LOCAL_MODULE)–以PRIVATE_、NDK_、或APP_(内部使用)开始的名称–小写的名称(例如’my-dir’,内部使用)如果你需要在
Android.mk中定义自己的变量的话,我们建议使用MY-前缀,一个简单的例子:—————————-MY_SOURCES : foo.cifneqMY_CONFIG_BARMY_SOURCES bar.cendifLOCAL_SRC_FILES MY_SOURCES—————————-我们继续:NDK提供的变量:在您的
Android.mk文件被解析之前这些GNU Make变量由编译系统定义,注意,在某些情况下,NDK可能被解析几次,每次以不同的变量的定义解析的CLEAR_VARSCLEAR_VARS这个变量由系统提供,功能是清理掉所有以LOCAL_开头的内容,再开始一个新的模块之前,你必须包括这段脚本include CLEAR_VARSBUILD_SHARED_LIBRARY在编译脚本中收集所有以LOCAL_开头的信息并且决定从列出的源代码中编译一个目标共享库。
注意,你必须定义了LOCAL_MODULE和LOCAL_SRC_FILES变量,使用它的时候,可以这样定义include BUILD_SHARED_LIBRARY注意,我们会生成一个以libltmodule_namegt.so为名的文件BUILD_STATIC_LIBRARY用来构建一个静态库,该静态库将不会被拷贝到你的project/packages下,但是可以被用于动态库 2用来构建一个静态库,该静态库将不会被拷贝到你的project/packages下,但是可以被用于动态库看下面的LOCAL_STATIC_LIBRARY和LOCAL_WHOLE_STATIC_LIBRARY介绍例如:include BUILD_STATIC_LIBRARY注意,这将生成一个libltmodule_namegt.a为名字的模块PREBUILD_SHARED_LIBRARY在编译脚本中用于指定一个预先编译的动态库,不像BUILD_SHARED_LIBRARY和BUILD_STATIC_LIBRARY,LOCAL_SRC_FILES的预先共享库必须是一个单独的路径(如:foo/libfoo.so),而不是源文件。
你可以在另一个模块中引用预编译的库(参见docs/pribuilds.html)PRIBUILD_STATIC_LIBRARY这个变量类似于PREBUILD_SHARED_LIBRARY,但是是针对静态库的,详见docs/prebuilds.htmlTARGET_ARCHTARGET_ARCH指框架中CPU的名字已经被
Android开源代码明确指出了,这里的arm包含了任何ARM-独立结构的架构,以及每个独立的CPU版本TARGET_PLATFORMAndroid平台的名字在
Android.mk中被解析,比如”
android-3〃对应
Android 1.5系统镜像,对于平台的名称对应
Android系统的列表,请看docs/STABLE-APIS.htmlTARGET_ARCH_ABI在
Android.mk中被解析时指CPUABI的名字。
目前支持的两个值armeabi for ARMv5TEarmeabi-v7a注意,到
Android NDK 1.6_r1,这个值被简化为”arm”。
然而,这个值被重定义可以更好的匹配
Android平台内部使用的是什么更多的信息可以参见docs/CPU-ARCH-ABIS.html未来的NDK版本中得到支持,它们会有一个不同的名字,注意所有基于ARM的ABI都会有一个”TARGET_ARCH”被定义给arm,但也有可能有不同的”TARGET_ARCH_ABI”TARGET_ABI目标平台和ABI的链接,这里要定义TARGET_PLATFORM-TARGET_ARCH_ABI它们都非常有用,特别是当你想测试一下具体的系统镜像在一个真实设备环境的时候默认地,这个是”
android-3-armeabi”到
Android NDK 16_R1版本,使用”
android-3-arm”作为默认NDK提供的宏功能——————————–以下是使用GNU make的宏功能,必须通过使用”call ltfunctiongt”,返回一个文本信息。
my-dir返回最后包含的makefile的路径,这通常是当前
Android.mk所在目录的路径,在
Android.mk开始之前定义LOCAL——PATH是很有用的。
在
Android.mk文件的开始位置定义LOCAL_PATH :call my-dir…声明一个模块include LOCAL_PATH/foo/
Android.mkLOCAL_PATH :call my-dir…声明另一个模块这里的问题是第二次调用”my-dir”定义LOCAL_PATH替换PATH为PATH/foo,由于在此之前执行过。
对于这个原因,最好是将额外的其他所有东西都在
Android.mk中包含进来LOCAL_PATH :call my-dir…声明一个模块LOCAL_PATH :call my-dir 3LOCAL_PATH :call my-dir…声明另一个模块在
Android.mk的最后额外包括进来include LOCAL_PATH/foo/
Android.mk如果这样不方便的话,保存第一个my-dir调用的值到另一个变量中,例如MY_LOCAL_PATH :call my-dirLOCAL_PATH :MY_LOCAL_PATH…声明一个模块include LOCAL_PATH/foo/
Android.mkLOCAL_PATH :MY_LOCAL_PATH…声明另一个模块all-subdir-makefiles返回一个
Android.mk文件所在位置的列表,以及当前的my-dir的路径。
比如sources/foo/
Android.mksources/foo/lib1/
Android.mksources/foo/lib2/
Android.mk如果sources/foo/
Android.mk包含了这行语句include call all-subdir-makefiles那么,它将会自动将sources/foo/lib1/
Android.mk和sources/foo/lib2/
Android.mk包含进来。
此功能可以用于提供深层嵌套的源代码目录build system的层次结构。
请注意,默认情况下,NDK只会寻找sources/
Android.mkthis-makefile返回当前makefile的路径(也就是那个功能被调用了)parent-makefile返回makefile的包含树,也就是包含Makefile当前的文件grand-parent-makefile你猜?import-module一个允许你通过名字找到并包含另一个模块的的
Android.mk的功能,例如call import-moduleltnamegt这将会找到通过NDK_MODULE_PATH环境变量引用的模块ltnamegt的目录列表,并且将其自动包含到
Android.mk中详细信息请参阅:docs/IMPORT-MODULE.html模块变量描述:———————————-下面的这些变量是用来描述怎样用你的模块来编译系统的。
你可以定义它们中的一些比如“include CLEAR_VARS”和”include BUILD_XXX”,正如前面所写的,CLEAR_VARS是一个可以取消定义/清楚所有变量的脚本。
LOCAL_PATH这个变量是用来给出当前文件的路径。
您比系再您的
Android.mk开始位置定义:LOCAL_PATH :call my-dir注意,这个变量是不被CLEAR_VARS清除的,其他的都要被清除(我们可以定义几个模块到一个文件中)LOCAL_MODULE这个是你模块的名称,它在你的所有模块中名称必须是唯一的,并且不能包含空格。
你必须在包含任何BUILD-XXX脚本之前定义它。
默认情况下,模块的名称决定了生成的文件的名称,例如libltfoogt.so,它是foo模块的名字。
你可以用LOCAL_MODULE_FILENAME覆盖默认的那一个LOCAL_MODULE_FILENAME这个变量是可选的,并且允许你重新定义生成文件的名字。
默认的,模块ltfoogt将始终生成libltfoogt.a或者libltfoogt.so文件,这是标准的UNIX公约你可以通过LOCAL_MODULE_FILENAME覆盖它LOCAL_MODULE :foo-version-1LOCAL_MODULE_FILENAME :libfoo 4LOCAL_MODULE_FILENAME :libfoo注意:你不能将文件路径或者文件扩展名写到LOCAL_MODULE_FILENAME里,这些将有build system自动处理。
LOCAL_SRC_FILES这是你模块中将要编译的源文件列表。
只列出将被传递到编译器的文件,因为build system自动为您计算了它们的依赖。
注意:源文件的名称都是相对LOCAL_PATH的,您可以使用路径组件,例如LOCAL_SRC_FILES :foo.ctoto/bar.c注意:在build system时请务必使用UNIX风格的斜杠/,windows风格的斜杠将不会得到处理LOCAL_CPP_EXTENSION这是个可选的变量,可以被定义为文件扩展名为c的源文件,默认是”.cpp”,但是你可以改变它,比如LOCAL_CPP_EXTENSION:.cxxLOCAL_C_INCLUDES可选的路径列表,相对于NDK的根目录,当编译所有的源文件(C、C、或者汇编)时将被追加到搜索路径中例如:LOCAL_C_INCLUDES:sources/foo或者LOCAL_C_INCLUDES:LOCAL_PATH/../foo这些都在任何相应列入标志之前被放置在LOCAL_CFLAGS / LOCAL_CPPFLAGS当用用ndk-gdb启动本机调试时,LOCAL_C_INCLUDES也会自动被使用到LOCAL_CFLAGS当编译C/C源文件时传递一个可选的编译器标志。
这对于指定额外的宏定义或编译选项很有用重要提示:尽量不要改变
Android.mk中的优化/调试级别,这个可以通过在Application.mk中设置相应的信息来自动为你处理,并且会会让NDK生成在调试过程中使用的有用的数据文件。
注意:在
Android-ndk-1.5_r1中,只使用于C源文件,而不适用于C源文件。
在匹配所有
Android build system的行为已经得到了纠正。
(现在你可以为C源文件使用LOCAL_CPPFLAGS来指定标志)它可以用LOCAL_CFLAGS -Iltpathgt来指定额外的包含路径,然而,如果使用LOCAL_C_INCLUDES会更好,因为用ndk-gdk进行本地调试的时候,那些路径依然是需要使用的LOCAL_CXXFLAGSLOCAL_CPPFLAGS的别名。
请注意,这个标志在NDK的未来的版本中将会消失LOCAL_CPPFLAGS当只编译C源代码的时候,将传递一个可选的编译器标志。
它们将会出现再LOCAL_CFLAGS之后。
注意:在
Android NDK-1.5_r1版本中,相应的标志可以应用于C或C源文件上。
在配合完整的
Android buildsystem的时候,这已经得到了纠正。
(你可以使用LOCAL_CFLAGS去指定C或C源文件)LOCAL_STATIC_LIBRARIES静态库模块的列表通过BUILD_STATIC_LIBRARY创建应与此模块链接。
这仅仅是为了使动态库敏感。
LOCAL_SHARED_LIBRARY共享库的列表“模块”,这个模块依赖于运行时.这在链接的时候和在生成的文件中嵌入相应的信息是非常必要的LOCAL_WHOLE_STATIC_LIBRARIESLOCAL_WHOLE_STATIC_LIBRARIES是一个用于表示相应的库模块被用作为“整个档案”到链接程序的变量。
当几个静态库之间有循环依赖关系的时候,通常是很有益的。
注意,当用来编译一个动态库的时候,这将迫使你将所有的静态库中的对象文件添加到最终的二进制文件中。
但生成可执行程序时,这是不确定的。
LOCAL_LDLIBS当额外的链接标志列表被用于在编译你的模块时,通过用”-l”前缀的特定系统库传递名字是很有用的。
例如,下面的旧爱哪个告诉你生成一个在加载时链接到/system/lib/libz.so的模块。
LOCAL_LDLIBS :-lzLOCAL_ALLOW_UNDEFINED_SYMBOLS默认情况下,当试图编译一个共享库的时候遇到任何未定义的引用都可能导致”未定义符号”undefined symbol的错误。
这在你的源代码中捕获bug会很有用。
5然而,但是由于某些原因,你需要禁用此检查的话,设置变量为”true”即可。
需要注意的是,相应的共享库在运行时可能加载失败。
LOCAL_ARM_MODE默认情况下,在”thumb”模式下会生成ARM目标二进制,其中每个指令都是16位宽。
你可以定义这个变量为”arm”,如果你想在”arm”模式下(32位指令)强迫模块对象文件的生成。
例如:LOCAL_ARM_MODE : arm注意,你需要执行编译系统为在ARM模式下通过文件的名字增加后缀的方式编译指定的源文件。
比如:LOCAL_SRC_FILES :foo.c bar.c.arm这会告诉编译系统一直以ARM模式编译”bar.c”并且通过LOCAL_ARM_MODE的值编译foo.c。
注意:在Application.mk文件中设置APP_OPTIM为”debug”也会强制ARM二进制文件的生成。
这是因为工具链调试其中的bug不会处理thumb代码。
LOCAL_ARM_NEON定义这个变量为”true”会允许在你的C或C源文件的GCC的内部函数中使用ARM高级SIMD(又名NEON),以及在聚合文件中的NEON指令。
当针对”armeabi-v7a”ABI对应的ARMv7指令集时你应该定义它。
注意,并不是所有的ARMv7都是基于NEON指令集扩展的CPU,你应该执行运行时来检测在运行时中这段代码的安全。
另外,你也可以指定特定的源文件,比如用支持NEON”.neon”后缀的源文件也可以被编译。
LOCAL_SRC_FILES :foo.c.neon bar.c zoo.c.arm.neon在这个例子中,”foo.c”将会被编译在thumbneon模式中,”bar.c”以thumb模式编译,zoo.c以armneon模式编译。
注意,如果你使用两个的话,”.neon”后缀必须出现在”.arm”后缀之后(就是foo.c.arm.neon可以工作,但是foo.c.neon.arm不工作)LOCAL_DISABLE_NO_EXECUTEAndroid NDK r4开始添加了支持”NX位”安全功能特性。
它是默认启用的,如果你需要的话,可以通过设置变量为“true”来禁用它。
注意:此功能不修改ABI,并且只在ARMv6及以上的CPU设备的内核上被启用。
更多信息,可以参见:http://en.wikipedia.org/wiki/NX_bithttp://www.gentoo.org/proj/en/hardened/gnu-stack.xmlLOCAL_EXPORT_CFLAGS定义这个变量用来记录C/C编译器标志集合,并且会被添加到其他任何以LOCAL_STATIC_LIBRARIES和LOCAL_SHARED_LIBRARIES的模块的LOCAL_CFLAGS定义中。
例如:这样定义”foo”模块include CLEAR_VARSLOCAL_MODULE :fooLOCAL_SRC_FILES :foo/foo.cLOCAL_EXPORT_CFLAGS :-DFOO1include BUILD_STATIC_LIBRARY另一个模块,叫做”bar”,并且依赖于上面的模块include CLEAR_VARSLOCAL_MODULE :barLOCAL_SRC_FILES :bar.cLOCAL_CFLAGS:-DBAR2LOCAL_STATIC_LIBRARIES:fooinclude BUILD_SHARED_LIBRARY然后,当编译bar.c的时候,标志”-DFOO1 -DBAR2〃将被传递到编译器。
输出的标志被添加到模块的LOCAL_CFLAGS上,所以你可以很容易复写它们。
它们也有传递性:如果”zoo”依赖”bar”,“bar”依赖”foo”,那么”zoo”也将继承”foo”输出的所有标志。
最后,当编译模块输出标志的时候,这些标志并不会被使用。
在上面的例子中,当编译foo/foo.c时,-DFOO1将不会被传递给编译器。
6LOCAL_EXPORT_CPPFLAGS类似LOCAL_EXPORT_CFLAGS但适用于C标志。
LOCAL_EXPORT_C_INCLUDES类似LOCAL_EXPORT_C_CFLAGS但是只有C能包含路径,如果”bar.c”想包含一些由”foo”模块提供的头文件的时候这会很有用。
LOCAL_EXPORT_LDLIBS类似于LOCAL_EXPORT_CFLAGS但是只用于链接标志。
注意,引入的链接标志将会被追加到模块的LOCAL_LDLIBS,这是因为UNIX连接器的工作方式。
当模块foo是一个静态库的时候并且代码依赖于系统库时会很有用的。
LOCAL_EXPORT_LDLIBS可以用于输出依赖,例如:include CLEAR_VARSLOCAL_MODULE : fooLOCAL_SRC_FILES : foo/foo.cLOCAL_EXPORT_LDLIBS : -lloginclude BUILD_STATIC_LIBRARYinclude CLEAR_VARSLOCAL_MODULE : barLOCAL_SRC_FILES : bar.cLOCAL_STATIC_LIBRARIES : fooinclude BUILD_SHARED_LIBRARY这里,在连接器命令最后,libbar.so将以-llog参数进行编译来表明它依赖于系统日志库,因为它依赖于foo。
LOCAL_FILTER_ASM这个变量定义了一个shell命令,将用于过滤,从你的LOCAL_SRC_FILES中产生的或者聚合文件。
当它被定义了,将会出现如下的情况:–任何C或C源文件将会生成到一个临时的聚合的文件中(而不是被编译成目标文件)–任何临时聚合文件,任何在LOCAL_SRC_FILES中列出的聚合文件将通过LOCAL_FILER_ASM命令生成另一个临时聚合文件–这些过滤聚合文件被编译成目标文件。
换种说法,如果LOCAL_SRC_FILES : foo.c bar.SLOCAL_FILTER_ASM : myasmfilterfoo.c –1–gt OBJS_DIR/foo.S.original –2–gt OBJ.