打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
androidNDK编译中文版2
android NDK编译 中文版2
(2012-07-24 15:47:05)
分类:android
LOCAL_NO_MANIFEST
如果你的Package没有Manifest(AndroidManifest.xml),你可以设置
LOCAL_NO_MANIFEST:=true.
------分隔符,方便下次编辑修改------
If your packagedoesn't have a manifest (AndroidManifest.xml), thenset
LOCAL_NO_MANIFEST:=true.
The common resourcespackage does this.
LOCAL_PACKAGE_NAME
LOCAL_PACKAGE_NAME变量是一个App的名字,例如:Dialer、Contacts等等。它可能在我们使用ant编译系统编译App时会发生改变。
LOCAL_PACKAGE_NAME isthe name of an app. For example, Dialer, Contacts, etc. This willprobably change or go away when we switch to an ant-based buildsystem for the apps.
LOCAL_PATH
LOCAL_PATH := $(callmy-dir):每个Android.mk文件都必须以定义LOCAL_PATH变量开始,其目的是为了定位源文件的位置。例如:
LOCAL_PATH :=$(my-dir)
my-dir宏函数使用的是MAKEFILE_LIST变量,你必须在include其它任何makefile之前来调用它。另外,考虑到当你include任何子目录时都要重新设置LOCAL_PATH,你必须在include它们之前设置它。
The directory yourAndroid.mk file is in. You can set it by putting the following asthe first line in your Android.mk:
LOCAL_PATH :=$(my-dir)
The my-dir macro usesthe MAKEFILE_LIST variable, so you must call it before you includeany other makefiles. Also, consider that any subdirectories youinlcude might reset LOCAL_PATH, so do your own stuff before youinclude them. This also means that if you try to write severalinclude lines that reference LOCAL_PATH, it won't work, becausethose included makefiles might reset LOCAL_PATH.
LOCAL_PREBUILT_EXECUTABLES
LOCAL_PREBUILT_EXECUTABLES预编译including$(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用,指定需要复制的可执行文件。
When including$(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these toexecutables that you want copied. They're located automaticallyinto the right bin directory.
LOCAL_PREBUILT_LIBS
LOCAL_PREBUILT_LIBS变量是在预编译including$(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用, 指定需要复制的库.
When including$(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to librariesthat you want copied. They're located automatically into the rightlib directory.
LOCAL_SHARED_LIBRARIES
LOCAL_SHARED_LIBRARIES变量用来列出模块所需的共享库的列表,不需要加上.so后缀。例如:
LOCAL_SHARED_LIBRARIES :=/
libutils /
libui /
libaudio /
libexpat /
libsgl
------分隔符,方便下次编辑修改------
These are thelibraries you directly link against. You don't need to passtransitively included libraries. Specify the name without thesuffix:
LOCAL_SHARED_LIBRARIES := \
libutils\
libui\
libaudio\
libexpat\
libsgl
LOCAL_SRC_FILES
LOCAL_SRC_FILES变量必须包含一系列将被构建和组合成模块的C/C++源文件。
注意:不需要列出头文件或include文件,因为生成系统会为你自动计算出源文件的依赖关系。默认的C++源文件的扩展名是.cpp,但你可以通过定义LOCAL_DEFAULT_EXTENSION来指定一个扩展名。
The build systemlooks at LOCAL_SRC_FILES to know what source files to compile --.cpp .c .y .l .java. For lex and yacc files, it knows how tocorrectly do the intermediate .h and .c/.cpp files automatically.If the files are in a subdirectory of the one containing theAndroid.mk, prefix them with the directory name:
LOCAL_SRC_FILES :=\
file1.cpp\
dir/file2.cpp
LOCAL_STATIC_LIBRARIES
LOCAL_STATIC_LIBRARIES变量和LOCAL_SHARED_LIBRARIES类似,用来列出你的模块中所需的静态库的列表,你可以在你的module中包含一些想使用的静态库,通常我们使用共享库,但是有些地方,像在sbin下的可执行程序和主机上的可执行程序我们要使用静态库。例如:
LOCAL_STATIC_LIBRARIES :=/
libutils /
libtinyxml
------分隔符,方便下次编辑修改------
These are the staticlibraries that you want to include in your module. Mostly, we useshared libraries, but there are a couple of places, likeexecutables in sbin and host executables where we use staticlibraries instead.
LOCAL_STATIC_LIBRARIES := \
libutils\
libtinyxml
LOCAL_MODULE
LOCAL_MODULE变量必须定义,用来标识在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。如果有其它moudle中已经定义了该名称,那么你在编译时就会报类似这样的错误:
libgl2jnialready defined by frameworks/base/opengl/tests/gl2_jni/jni.Stop.
下面就是该错误的截图:
接下来就是修改你的module的名字了,或者找到跟你重名的module把它干掉,但不建议你那么做,因为有可能会带来未知的错误(你修改了别人的module的名字,而别人不一定知道,当他再编译或者做其它时,就会出错)。
LOCAL_MODULE is thename of what's supposed to be generated from your Android.mk. Forexmample, for libkjs, the LOCAL_MODULE is "libkjs" (the buildsystem adds the appropriate suffix -- .so .dylib.dll).
注意:编译系统会自动产生合适的前缀和后缀,例如:
LOCAL_MODULE :=screenshot
一个被命名为“screenshot”的共享库模块,将会生成“libscreenshot.so”文件。
补充1:变量命名的规范性
如果LOCAL_MODULE变量定义的值可能会被其它module调用时,就要考虑为其变量命名的规范性了。特别是在使用JNI时,既在LOCAL_JNI_SHARED_LIBRARIES变量中定义的值,最好要和LOCAL_MODULE变量定义的值保存一致(具体请参考LOCAL_JNI_SHARED_LIBRARIES变量的使用说明)。
这时的LOCAL_MODULE变量的命名最好以lib开头,既“libxxx”,例如:
LOCAL_MODULE :=libscreenshot
LOCAL_MODULE_PATH
通知编译系统将module放到其它地方而不是它通常的类型。如果你重写这个变量,确保你还要再设置LOCAL_UNSTRIPPED_PATH变量的值。如果你忘了设置LOCAL_UNSTRIPPED_PATH变量的值的话,就会报错。
Instructs the buildsystem to put the module somewhere other than what's normal for itstype. If you override this, make sure you also setLOCAL_UNSTRIPPED_PATH if it's an executable or a shared library sothe unstripped binary has somewhere to go. An error will occur ifyou forget to.
LOCAL_WHOLE_STATIC_LIBRARIES
LOCAL_WHOLE_STATIC_LIBRARIES 指定模块所需要载入的完整静态库(这些静态库在链接是不允许链接器删除其中无用的代码)。通常这在你想往共享库中增加一个静态库时是非常有用的,共享库就会接受到静态库暴露出的content,例如:
LOCAL_WHOLE_STATIC_LIBRARIES :=/
libsqlite3_android
------分隔符,方便下次编辑修改------
These are the staticlibraries that you want to include in your module without allowingthe linker to remove dead code from them. This is mostly useful ifyou want to add a static library to a shared library and have thestatic library's content exposed from the sharedlibrary.
LOCAL_WHOLE_STATIC_LIBRARIES :=\
libsqlite3_android
LOCAL_REQUIRED_MODULES
LOCAL_REQUIRED_MODULES 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块)
SetLOCAL_REQUIRED_MODULES to any number of whitespace-separated modulenames, like "libblah" or "Email". If this module is installed, allof the modules that it requires will be installed as well. This canbe used to, e.g., ensure that necessary shared libraries orproviders are installed when a given app isinstalled.
LOCAL_PRELINK_MODULE
LOCAL_PRELINK_MODULE变量用来规定是否需要预连接处理(默认需要,用来做动态库优化)。LOCAL_PRELINK_MODULE只有在编译.so的时候才会有的选项,主要是通过预链接的方式来加快程序启动和执行的速度,如果在你的代码(/jni/Android.mk)中有下面一条语句:
LOCAL_PRELINK_MODULE:= true
那么你要在build/core/prelink-linux-arm.map中定义你的库所需要使用的空间,如果不定义或者空间不够的话,在编译的时候就会报错。如下图所示:
当在build/core/prelink-linux-arm.map中定义了我们这里使用的libhello-jni.so库的空间之后,既在该文件中加入一条语句:
libhello-jni.so                   0x99E00000
注意:在prelink-linux-arm.map文件的开头部分有明确的规定,指定的内存取值范围分配给不同的部分使用,而我们的App的库也给指定了一个范围:
0x90000000 -0x9FFFFFFF Prelinked App Libraries
重新编译,就不会再报错了,下面的截图中很清晰地看到已经将libhello-jni.so库预编译成功了:
注意:
在给我们的应用库分配地址空间时,最好以1M为边界,地址空间大小按照由大到小的降序进行排序。
下面是对于Prelink的说明:
Prelink利用事先链接代替运行时链接的方法来加速共享库的加载,它不仅可以加快起动速度,还可以减少部分内存开销。程序运行时的动态链接尤其是重定位(relocation)的开销对于大型系统来说是很大的。动态链接和加载的过程开销很大,并且在大多数的系统上,函数库并不会常常被更动,每次程序被执行时所进行的链接动作都是完全相同的,对于嵌入式系统来说尤其如此。因此,这一过程可以改在运行时之前就可以预先处理好,即花一些时间利用Prelink工具对动态共享库和可执行文件进行处理,修改这些二进制文件并加入相应的重定位等信息,节约了本来在程序启动时的比较耗时的查询函数地址等工作,这样可以减少程序启动的时间,同时也减少了内存的耗用。
Prelink的这种做法当然也有代价的,每次更新动态共享库时,相关的可执行文件都需要重新执行一遍Prelink才能保证有效,因为新的共享库中的符号信息、地址等很可能与原来的已经不同了,这就是为什么androidframework代码一改动,这时候就会导致相关的应用程序重新被编译。
LOCAL_JNI_SHARED_LIBRARIES
LOCAL_JNI_SHARED_LIBRARIES变量主要是用在JNI的编译中,如果你要在你的Java代码中引用JNI中的共享库*.so,此变量就是共享库的名字。
那么你要注意的一点是:在你的Project根目录下的Android.mk中要定义此变量用来引用你要使用的JNI中的共享库*.so。例如:
$(Project)/Android.mk
LOCAL_JNI_SHARED_LIBRARIES :=libsanangeles
而在你的jni目录下的Android.mk中则要定义LOCAL_MODULE变量的值,一定要让这两个变量的值相同。假如你没有这么做,而是像这样:
$(Project)/jni/Android.mk
LOCAL_MODULE :=sanangeles
那么,在编译的时候就会出现下图的错误:
这说明在编译libsanangeles.so找不到其规则,因为在上面的代码中定义的是sanangeles。重新修改LOCAL_MODULE变量的值:
$(Project)/jni/Android.mk
LOCAL_MODULE :=libsanangeles
即可正常编译。
LOCAL_EXPORT_CFLAGS
定义这个变量用来记录C/C++编译器标志集合,并且会被添加到其他任何以LOCAL_STATIC_LIBRARIES和LOCAL_SHARED_LIBRARIES的模块的LOCAL_CFLAGS定义中。例如:这样定义"foo"模块:
foo/Android.mk
include$(CLEAR_VARS)
LOCAL_MODULE:=foo
LOCAL_SRC_FILES:=foo/foo.c
LOCAL_EXPORT_CFLAGS:=-DFOO=1
include$(BUILD_STATIC_LIBRARY)
另一个模块,叫做"bar",并且依赖于上面的模块:
bar/Android.mk
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_EXPORT_CPPFLAGS
类似LOCAL_EXPORT_CFLAGS,但适用于C++标志。
具体请参考LOCAL_EXPORT_CFLAGS条目。
LOCAL_EXPORT_C_INCLUDES
类似LOCAL_EXPORT_CFLAGS,但是只有C能包含路径,如果"bar.c"想包含一些由"foo"模块提供的头文件的时候这会很有用。
具体请参考LOCAL_EXPORT_CFLAGS条目。
LOCAL_EXPORT_LDLIBS
类似于LOCAL_EXPORT_CFLAGS,但是只用于链接标志。注意,引入的链接标志将会被追加到模块的LOCAL_LDLIBS,这是由UNIX连接器的工作方式决定的。
当模块foo是一个静态库的时候并且代码依赖于系统库时会很有用的。LOCAL_EXPORT_LDLIBS可以用于输出依赖,例如:
#Frist build thestatic library libfoo.a
include$(CLEAR_VARS)
LOCAL_MODULE :=foo
LOCAL_SRC_FILES :=foo/foo.c
LOCAL_EXPORT_LDLIBS:= -llog
include$(BUILD_STATIC_LIBRARY)
#Then build theshared library libbar.so
include$(CLEAR_VARS)
LOCAL_MODULE :=bar
LOCAL_SRC_FILES :=bar.c
LOCAL_STATIC_LIBRARIES := foo
include$(BUILD_SHARED_LIBRARY)
这里,在连接器命令最后,libbar.so将以”-llog”参数进行编译来表明它依赖于系统日志库,因为它依赖于foo。
LOCAL_ALLOW_UNDEFINED_SYMBOLS
默认情况下,当试图编译一个共享库的时候遇到任何未定义的引用都可能导致"未定义符号"(undefinedsymbol)的错误。这在你的源代码中捕获bug会很有用。
然而,但是由于某些原因,你需要禁用此检查的话,设置变量为"true"即可。需要注意的是,相应的共享库在运行时可能加载失败。
LOCAL_ARM_MODE
LOCAL_ARM_MODE变量主要是应用与嵌入式产品的编译系统中,可以指定为arm模式。例如:
LOCAL_ARM_MODE :=arm
注意:你需要执行编译系统为在ARM模式下通过文件的名字增加后缀的方式编译指定的源文件。例如:
LOCAL_SRC_FILES:=foo.c bar.c.arm
这会告诉编译系统一直以ARM模式编译"bar.c",并且通过LOCAL_ARM_MODE的值编译foo.c。
2.2.2.BUILD_XXX变量
2.2.2.1.BUILD_SHARED_LIBRARY
BUILD_SHARED_LIBRARY:指明要编译生成动态共享库。指向一个生成脚本,这个脚本通过LOCAL_XXX变量收集关于组件的信息,并决定如何根据你列出来的源文件生成目标共享库。
注意:在include这个脚本文件之前你必须至少已经定义了LOCAL_MODULE和LOCAL_SRC_FILES。例如:
include$(BUILD_SHARED_LIBRARY)
注意:这会生成一个名为lib$(LOCAL_MODULE).so的动态库。
2.2.2.2.BUILD_STATIC_LIBRARY
BUILD_STATIC_LIBRARY与BUILD_SHARED_LIBRARY类似,但用来生成目标静态库。静态库不会被拷贝至你的project/packages文件夹下,但可用来生成共享库。
例如:
include$(BUILD_STATIC_LIBRARY)
注意:这会生成一个静态库,名叫lib$(LOCAL_MODULE).a的静态库。
2.2.2.3.BUILD_PACKAGE
BUILD_PACKAGE变量用于在最好编译时生成*.apk,例如:
include$(BUILD_STATIC_LIBRARY)
注意:这会生成一个apk安装包,名字就叫$(LOCAL_MODULE).apk的安装包。
2.2.3.其它变量
2.2.3.1.CLEAR_VARS
CLEAR_VARS变量是生成系统提供的,它指向一个特殊的GNU Makefile,它将会为你自动清除许多名为LOCAL_XXX的变量(比如:LOCAL_MODULE、LOCAL_SRC_FILES、LOCAL_STATIC_LIBRARIES等),但LOCAL_PATH是例外,它不会被清除。
注意:这些变量的清除是必须的,因为所有的控制文件是在单一的Makefile,执行环境中解析的,在这里所有的变量都是全局的。
2.2.3.2.TARGET_PLATFORM
TARGET_PLATFORM:当解析该Android.mk文件时用它来指定Andoid目标平台的名称。例如:android-3与Android 1.5相对应。
2.2.4.NDK提供的宏函数
下面是GNU Make的宏函数,必须通过这样的形式调用:
$(call<function>)
2.2.4.1.my-dir
my-dir:返回放置当前Android.mk的文件夹相对于NDK生成系统根目录的路径。可用来在Android.mk的开始处定义LOCAL_PATH的值:
LOCAL_PATH := $(callmy-dir)
2.2.4.2.all-subdir-makefiles
all-subdir-makefiles:返回my-dir子目录下的所有Android.mk。例如:
代码的结构如下:
sources/foo/Android.mk
sources/foo/lib1/Android.mk
sources/foo/lib2/Android.mk
如果sources/foo/Android.mk里有这样一行:
include $(callall-subdir-makefiles)
那么,它将会自动地包含sources/foo/lib1/Android.mk和
sources/foo/lib2/Android.mk。这个函数能将深层嵌套的代码文件夹提供给生成系统。
注意:默认情况下,NDK仅在source/*/Android.mk里寻找文件。
2.2.4.3.this-makefile
this-makefile:返回当前Makefile所在目录的路径。
2.2.4.4.parent-makefile
parent-makefile:返回父Makefile所在目录makefile的路径。
2.2.4.5.import-module
一个允许你通过名字找到并包含另一个模块的的Android.mk的功能,例如:
$(callimport-module,<name>)
这将会找到通过NDK_MODULE_PATH环境变量引用的模块<name>的目录列表,并且将其自动包含到Android.mk中。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
android平台的jni
Android.mk官方说明 中文翻译
Android NDK开发指南---Android.mk文件
android 集成第三方静态库的编译方法
Android.mk 文件语法详解
Android.mk 翻译(说明)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服