最近为java层将一个静态库通过jni层封装成了一个动态库工他们调用,遇到了一些编译上的疑惑,所以索性将其彻底搞清楚算了,免得以后误事。
下面的图片列出了所有相关文件,可以看到引用静态库的文件是com_xxx.cpp文件,而.a文件是放在lib目录下的libHWRecog.a,而库提供出来的头文件在include下的两个.h文件。
源码文件写好了之后,首先就是要编译通过吧,这里有两个方案来写mk文件:第一种采用类似c/c++的编译方式:直接指定库名字;第二种采用android的独特方式:需要将静态库假意生成到out目录的专用静态库目录下去。
编译模块命令:
TARGET_PRODUCT=ginwave73_gb ./mk orig -t mm frameworks/base/freestylus/jni/
第一种方式:类似c/c++直接指定的编译方式
在linux下编程时,当使用到了标准或者特定的库时我们大多使用如下的形式来指定名字或者目录:
gcc –I -L -l -l xxx.c –o xxx
如:gcc –I./include –L./lib –lHWrecog –lm –lc {–static} test.c –o test
gcc命令的常用选项见后面附录A。
那么在android的编译过程中,也可以使用类似于这种方式来指定参数,不过在这之前,我们需要了解以下一些编译变量:
LOCAL_C_INCLUDES
LOCAL_CC
LOCAL_CFLAGS
LOCAL_CPP_EXTENSION
LOCAL_CPPFLAGS
LOCAL_CXX
LOCAL_LDLIBS
LOCAL_LDFLAGS
LOCAL_FORCE_STATIC_EXECUTABLE
这些LOCAL_开头的变量都是模块编译内的局部变量,因为通常在Android.mk开头都要包含:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
这两句,特别是include $(CLEAR_VARS)这个会清除上一个模块编译时候留下的所有LOCAL_变量,以准备给当前模块使用。
LOCAL_C_INCLUDES:额外的C/C++编译头文件路径,用LOCAL_PATH表示本文件所在目录,像gcc的-I参数。如:LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_CC:另外指定c编译器,不使用默认的。
LOCAL_CFLAGS:为C编译器传递额外的参数(如宏定义),举例:LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1
LOCAL_CPP_EXTENSION:如果你的C++文件不是以cpp为文件后缀,你可以通过LOCAL_CPP_EXTENSION指定C++文件后缀名
如:LOCAL_CPP_EXTENSION := .cc注意统一模块中C++文件后缀必须保持一致。
LOCAL_CPPFLAGS:传递额外的参数给C++编译器,如:LOCAL_CPPFLAGS += -ffriend-injection -DLIBUTILS_NATIVE
LOCAL_CXX:指定C++编译器
下面的三个编译变量都是和ld有关的,所以比较重要:
LOCAL_LDLIBS:故名思议,ldlibs,就是指定那些存在于系统目录下本模块需要连接的库。如果某一个库既有动态库又有静态库,那么在默认情况下是链接的动态库而非静态库。
如:LOCAL_LDLIBS += -lm –lz –lc -lcutils –lutils –llog …
如果你的Android.mk文件中只有这么一行,那么将会采用动态链接。这个类似于上面用gcc编译时直接指定库是一样的道理。
LOCAL_LDFLAGS:这个编译变量传递给链接器一个一些额外的参数,比如想传递而外的库和库路径给ld,或者传递给ld linker的一些链接参数,-On,-EL{B}(大小端字节序),那么就要加到这个上面,如: