1构建多个共享库
为了建立可供住应用程序使用的模块,必须将该模块变为共享库。Android ndk构建系统将BUILD_SHARE_LIBRARY变量设置成 build-shared-library.mk文件位置。该makefile片段包含了将源文件构建和组装成共享库的必要过程:
include $(BUILD_SHARE_LIBRARY )
上一篇中,就是一个简单的模块;然而,除非模块需要特殊处理,否则Android.mk文档将包含一模一样的流程和指令。
2构建多个共享库
基于不同的应用程序的体系结构,一个单独的Android.mk文档可能产生多个共享库模块。为了达到这个目的,需要如下程序清单Android.mk文档中定义多个模块。
LOCAL_PATH := $(call my-dir)
#
#模块1
#
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
$(LOCAL_PATH)/src
LOCAL_SRC_FILES := src/hello-jni.c
LOCAL_MODULE := NativeLib
include $(BUILD_SHARED_LIBRARY)
#
# 模块2
#
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
$(LOCAL_PATH)/src
LOCAL_SRC_FILES := src/hello-jni2.c
LOCAL_MODULE := NativeLib2
include $(BUILD_SHARED_LIBRARY)
重新编译构建文档之后,Android NDK构建系统会产生两个定义的共享库
3构建静态库
Android NDK构建系统也支持静态库。实际的Android应用程序并不直接使用静态库,并且应用程序包中也不包含静态库。静态库可以用来构建共享库。例如,在将第三方代码添加到现有的原生项目中,不用直接将第三方源代码包括在原生项目中,而是将第三方代码编译成静态库然后并入共享库,如下面程序。
LOCAL_PATH := $(call my-dir)
#
# 第三方库
#
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
$(LOCAL_PATH)/src
LOCAL_SRC_FILES := src/staticlib.c
LOCAL_MODULE := StaticLib
include $(BUILD_STATIC_LIBRARY)
#
# 目标库
#
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
$(LOCAL_PATH)/src
LOCAL_SRC_FILES := src/hello-jni.c
LOCAL_MODULE := NativeLib
LOCAL_STATIC_LIBRARIES := StaticLib
include $(BUILD_SHARED_LIBRARY)
将第三方代码模块生成模块静态库之后,共享库就可以通过将它的模块名称添加到LOCAL_STATIC_LIBRARIES变量中来使用该模块
4,用共享库共享通用模块
静态库可以保证源代码模块化;但是当静态库与共享库相连接时,他就变成了共同共享库的一部分。在多个共享库的情况下,多个共享库与同一个静态库连接时,需要将通用模块的多个副本与不同共享库重复相连,这样就增加了应用程序的大小,在这种情况下,不同构建静态库,而是将通用模块作为共享库建立起来,而动态库连接依赖模块以便消除重复的副本。
LOCAL_PATH := $(call my-dir)
#
# 第三方库
#
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
$(LOCAL_PATH)/src
LOCAL_SRC_FILES := src/staticlib.c
LOCAL_MODULE := StaticLib
include $(BUILD_SHARED_LIBRARY)
#
# 目标库
#
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
$(LOCAL_PATH)/src
LOCAL_SRC_FILES := src/hello-jni.c
LOCAL_MODULE := NativeLib
LOCAL_SHARED_LIBRARIES := StaticLib
include $(BUILD_SHARED_LIBRARY)
#
# 目标库
#
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
$(LOCAL_PATH)/src
LOCAL_SRC_FILES := src/hello-jni2.c
LOCAL_MODULE := NativeLib2
LOCAL_SHARED_LIBRARIES := StaticLib
include $(BUILD_SHARED_LIBRARY)
5.在多个ndk项目间共享模块
同时使用静态库和共享库时,可以在模块间共享通用模块,但要说明的所有的模块必须数据属于同一个NDk项目,从R5开始,android NDK 也允许在NDK项目间共享和重建模块。考虑前面讲过的实例,可以通过以下步骤在过多个ndk项目间共享。
作为共享模块,需要自己的Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
$(LOCAL_PATH)/src
LOCAL_SRC_FILES := src/hello-jni.c
LOCAL_MODULE := NativeLib
#LOCAL_SHARED_LIBRARIES :=StaticLib
include $(BUILD_SHARED_LIBRARY)
$(call import-module,test/StaticLib)
将原先模块移动到项目外面,将import-modules函数宏调用放在Android.mk文档的尾部。
import-modules 函数需要先定位共享模块,然后再将它导入到NDK项目中,默认情况下,,import-modules函数宏值搜索<Android NDK>/source 目录中,为了搜索 共享模块目录,顶一个名为NDK_MODULE_PATH的新的环境变量并将它设置为共享模块的根目录,
6 用prebuild库
使用共享模块要求有共享模块的源代码,Android NDK构建系统简单的把这些资源文件包含在NDK项目中并每次构建它们,Android NDK也提供对Prebuild库的支持。在下面的情况,Prebuild库是非常有用的
- 想在不发布源代码的情况下将模块发布给别人
- 想使用共享模块的预建版来加速构建过程。
尽管已经被编译了,但预建模块仍需要一个Android.mk构建文档,如下面编译ffmpeg
LOCAL_PATH := $(call my-dir)
# prepare libX
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := libavcodec.a
include $(PREBUILT_STATIC_LIBRARY)
# prepare libX
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := avfilter
LOCAL_SRC_FILES := libavfilter.a
include $(PREBUILT_STATIC_LIBRARY)
# prepare libX
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := avformat
LOCAL_SRC_FILES := libavformat.a
include $(PREBUILT_STATIC_LIBRARY)
# prepare libX
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := avutil
LOCAL_SRC_FILES := libavutil.a
include $(PREBUILT_STATIC_LIBRARY)
# prepare libX
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := postproc
LOCAL_SRC_FILES := libpostproc.a
include $(PREBUILT_STATIC_LIBRARY)
# prepare libX
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := swresample
LOCAL_SRC_FILES := libswresample.a
include $(PREBUILT_STATIC_LIBRARY)
# prepare libX
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := swscale
LOCAL_SRC_FILES := libswscale.a
include $(PREBUILT_STATIC_LIBRARY)
# prepare libX
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := x264
LOCAL_SRC_FILES := libx264.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_MODULE := live_jni
LOCAL_SRC_FILES := live_jni.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_CFLAGS := -D__STDC_CONSTANT_MACROS -Wno-sign-compare -Wno-switch -Wno-pointer-sign -DHAVE_NEON=1 -mfpu=neon -mfloat-abi=softfp -fPIC -DANDROID
LOCAL_STATIC_LIBRARIES := avfilter avformat avcodec postproc swresample swscale avutil x264
LOCAL_LDLIBS := -L$(NDK_ROOT)/platforms/$(APP_PLATFORM)/arch-arm/usr/lib -L$(LOCAL_PATH) -llog -ljnigraphics -lz -ldl
include $(BUILD_SHARED_LIBRARY)
LOCAL_SRC_FILES 变量指向的不是源文件,而是实际prebuilt库相对于LOCAL_PATH的位置。
prebuilt库定义中不包含任何关于该库所构建的实际机器体系结构的信息。开发人员需要确保prebuilt库是为与NDK项目相同的及其体系结构而构建的。
PREBUILT_STATIC_LIBRARY 变量指向prebuilt-shared-library.mk makefile片段。它什么都没构建,只是将prebuilt库复制到NDK项目的libs目录下。通过使PREBUILT_STATIC_LIBRARY 变量,静态库可以像共享库一样被用作PreBuil库,NDK项目可以像普通共享库一样使用PreBuilt库了