Android.mk是Android提供的一种makefile文件,用来指定诸如编译生成so库名、引用的头文件目录、需要编译的.c/.cpp文件和.a静态库文件等。@H_403_5@要掌握jni,就必须熟练掌握Android.mk的语法规范。@H_403_5@
@H_403_5@
由于该文件会被NDK的编译工具解析多次,因此应该尽量减少源码中声明变量,因为这些变量可能会被多次定义从而影响到后面的解析。这个文件的语法允许把源代码组织成模块,每个模块属于下列类型之一:
@H_403_5@
- APK程序:一般的Android程序,编译打包生成apk文件。
- JAVA库:java类库,编译打包生成jar包文件。
- C\C++应用程序:可执行的C/C++应用程序。
- C\C++静态库:编译生产C/C++静态库,并打包成.a文件。
- C\C++共享库:编译生成共享库(动态库),并打包成.so文件,有且只有共享库才能被安装/复制到APK包中。
- 单一的Android.mk文件:直接参考NDK的sample目录下的hello-jni项目,在这个项目中只有一个Android.mk文件
- 多个Android.mk文件:如果需要编译的模块比较多,我们可能会将对应的模块放置在相应的目录中,这样,我们可以在每个目录中定义对应的Android.mk文件(类似于上面的写法),最后,在根目录放置一个Android.mk文件,内容如下:include $(call all-subdir-makefiles)@H_403_5@只需要这一行就可以了,它的作用就是包含所有子目录中的Android.mk文件
- 多个模块共用一个Android.mk :这个文件允许你将源文件组织成模块,这个模块中含有:静态库(.a文件) 和动态库(.so文件)只有共享库才能被安装/复制到您的应用软件(APK)包中include $(BUILD_STATIC_LIBRARY)编译出的是静态库 ;include $(BUILD_SHARED_LIBRARY)编译出的是动态库@H_403_5@
@H_403_5@
sources/test/hello.c sources/test/Android.mk其中“hello.c”是一个JNI共享库,实现返回“hello world”字符串的原生方法。因此,Android.mk文件内容如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello LOCAL_SRC_FILES := hello.c include $(BUILD_SHARED_LIBRARY)解释一下这几行代码:
LOCAL_PATH := $(call my-dir) @H_403_5@: 一个Android.mk文件首先必须定义好LOCAL_PATH变量,用于在开发树中查找源文件。在这个例子中,宏函数my-dir由编译系统提供,用于返回当前路径(即包含Android.mk文件的目录)。
include $(CLEAR_VARS)@H_403_5@:CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE清除了LOCAL_PATH变量外的许多LOCAL_***变量(例如:LOCAL_MODULE、LOCAL_SRC_FILES等)。这是非常有必要的,因为所有的编译文件都在同一个GUN MKAE执行环境中,所有的变量都是全局变量,不清除容易引起解析错误。
LOCAL_MODULE := hello@H_403_5@:LOCAL_MODULE变量必须定义,用来标识在Android.mk文件描述的每一个模块。而且名称必须是唯一的,并且不能包含空格。编译系统会自动产生合适的前缀和后缀,比如一个被命名为hello的共享库模块,将会生成libhello.so文件。如果把库命名为libhello,编译系统将不会添加任何lib前缀,也会生成libhello.so文件。
LOCAL_SRC_FILES := hello.c@H_403_5@:LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的源代码文件。
include $(BUILD_SHARED_LIBRARY)@H_403_5@:BUILD_SHARED_LIBRARY是编译系统提供的变量,指向一个GNU Makefile脚本(应该就是build/core目录下的shared_library.mk),负责收集自从上次调用include $(CLEAR_VARS)以来,定义在LOCAL_***变量中的所有信息,并且决定编译什么,如何正确地去做,并根据其规则生成动态库。
自定义变量
以下是在 Android.mk中依赖或定义的变量列表,可以定义其他变量为自己使用,但是NDK编译系统保留下列变量名:
@H_403_5@
- -以 LOCAL_开头的名字(例如 LOCAL_MODULE)@H_403_5@
- -以 PRIVATE_,NDK_ 或 APP_开头的名字(内部使用)@H_403_5@
- -小写名字(内部使用,例如‘my-dir’)@H_403_5@
- -如果为了方便在 Android.mk 中定义自己的变量,建议使用 MY_前缀@H_403_5@@H_403_5@
@H_403_5@
声明共享库模块@H_403_5@
把共享库声明为一个独立模块。假如 libfoo.so 与 Android.mk 位于同一目录。则 Android.mk 应该这样写:@H_403_5@
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt # 模块名 LOCAL_SRC_FILES := libfoo.so # 模块的文件路径(相对于 LOCAL_PATH) include $(PREBUILT_SHARED_LIBRARY) # 注意这里不是 BUILD_SHARED_LIBRARY这个共享库将被拷贝到 $PROJECT/obj/local @H_403_5@和 $PROJECT/libs/<abi> (strip过的)
在其他模块中引用这个共享库@H_403_5@
在 Android.mk 中,将这个共享库的模块名加入 LOCAL_STATIC_LIBRARIES (静态库)或 LOCAL_SHARED_LIBRARIES (动态库)。@H_403_5@例如,使用 libfoo.so 的方法:@H_403_5@
include $(CLEAR_VARS) LOCAL_MODULE := foo-user LOCAL_SRC_FILES := foo-user.c LOCAL_SHARED_LIBRARY := foo-prebuilt include $(BUILD_SHARED_LIBRARY)
为共享库导出头文件@H_403_5@
这个共享库一般有相应的头文件,比如 libfoo.so 就有 foo.h。一个简单方法(在Android.mk中写)@H_403_5@
include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt LOCAL_SRC_FILES := libfoo.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY)
这样,使用该共享库的模块就会在它的 LOCAL_C_INCLUDES 变量加入该头文件搜索路径。@H_403_5@
@H_403_5@
#宏函数my-dir返回编译系统提供的当前路径,即Android.mk的目录@H_403_5@
#如(HelloWorld/proj.android/jni/XX)@H_403_5@
LOCAL_PATH :@H_403_5@= $(call my-dir)
#初始化模块 重置除LOCAL_PATH变量以外的所有变量 @H_403_5@
include@H_403_5@ $(CLEAR_VARS)
#导入库目录@H_403_5@
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos)
#模块名,唯一。@H_403_5@
LOCAL_MODULE :@H_403_5@= cocos2dcpp_shared
#模块文件名,唯一(可选)@H_403_5@
LOCAL_MODULE_FILENAME :@H_403_5@= libcocos2dcpp
#把.cpp .c .cc等实现文件的路径赋值给LOCAL_SRC_FILES@H_403_5@
我用的是C++版 所以后缀是.cpp 我们新建文件时,需要在这里添加路径。
LOCAL_SRC_FILES :@H_403_5@= hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp
#配置头文件的搜索范围@H_403_5@
LOCAL_C_INCLUDES :@H_403_5@= $(LOCAL_PATH)/../../Classes
#获取静态库@H_403_5@
LOCAL_WHOLE_STATIC_LIBRARIES :@H_403_5@= cocos2dx_static
#追加静态库@H_403_5@
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
# LOCAL_WHOLE_STATIC_LIBRARIES += Box2d_static@H_403_5@
# LOCAL_WHOLE_STATIC_LIBRARIES += cocosbuilder_static@H_403_5@
# LOCAL_WHOLE_STATIC_LIBRARIES += spine_static@H_403_5@
# LOCAL_WHOLE_STATIC_LIBRARIES += cocostudio_static@H_403_5@
# LOCAL_WHOLE_STATIC_LIBRARIES += cocos_network_static@H_403_5@
# LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static@H_403_5@
#根据编译器提供的变量BUILD_SHARED_LIBRARY生成动态库@H_403_5@
include@H_403_5@ $(BUILD_SHARED_LIBRARY)
#导入模块,以下是常用的几个模块@H_403_5@
$(call import-module@H_403_5@,.)@H_403_5@
$(call import-audio@H_403_5@/android@H_403_5@)@H_403_5@
# $(call import-module,Box2D)@H_403_5@
403_5@
403_5@
dio)@H_403_5@
403_5@
403_5@
以下是cocos2dx-3.2新建项目时生成的Android.mk文件,基本语法:@H_403_5@@H_403_5@
@H_403_5@
“#” 注释 “:=” 赋值 “+=” 追加 “$” 引用某变量的值如果文件少 直接在LOCAL_SRC_FILES这个变量里添加文件的路径就好了,若@H_403_5@有几十个文件,一个个添加还不累死,而且难维护,难扩展,易出错,。。。@H_403_5@@H_403_5@
LOCAL_PATH :@H_403_5@= $(call my-dir)
include@H_403_5@ $(CLEAR_VARS)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos)
LOCAL_MODULE :@H_403_5@= cocos2dcpp_shared
LOCAL_MODULE_FILENAME :@H_403_5@= libcocos2dcpp
#widcard为扩展通配符@H_403_5@
#遍历目录和子目录@H_403_5@
define walk
$(wildcard $(1@H_403_5@)) $(foreach e,$(wildcard $(1@H_403_5@)/*),$(call walk,$(e)))
endef
#遍历路径Classes下得目录和子目录文件,并存入ALLFILES变量中@H_403_5@
ALLFILES = $(call walk,$(LOCAL_PATH)/../../Classes)
#从ALLFILES目录中提取文件,并存入FILE_LIST中@H_403_5@
#.cc是Linux/Unix下为C++源文件的默认扩展名,与.cpp一个意思@H_403_5@
#.c 因为我要用到sqlite3.c @H_403_5@
FILE_LIST :@H_403_5@= hellocpp/main.cpp
FILE_LIST += $(filter %.cpp,$(ALLFILES))
FILE_LIST += $(filter %.c,$(ALLFILES))
FILE_LIST += $(filter %.cc,$(ALLFILES))
#搜索Classes下的子目录文件@H_403_5@
FILE_INCLUDES += $(shell find $(LOCAL_PATH)/../../Classes -type d)
#根据搜索到的文件名 编译资源文件@H_403_5@
LOCAL_SRC_FILES :@H_403_5@= $(FILE_LIST:@H_403_5@$(LOCAL_PATH)/%=%)
#提供搜索文件的路径@H_403_5@
LOCAL_C_INCLUDES :@H_403_5@= $(LOCAL_PATH)/../../Classes \
$(FILE_INCLUDES) \
#静态库@H_403_5@
LOCAL_WHOLE_STATIC_LIBRARIES :@H_403_5@= cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
#LOCAL_WHOLE_STATIC_LIBRARIES += Box2d_static@H_403_5@
#LOCAL_WHOLE_STATIC_LIBRARIES += cocosbuilder_static@H_403_5@
#LOCAL_WHOLE_STATIC_LIBRARIES += spine_static@H_403_5@
LOCAL_WHOLE_STATIC_LIBRARIES += cocostudio_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_network_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static
#编译动态库@H_403_5@
#导入静态库对应的模块@H_403_5@
$(call import-#$(call import-module,editor-support/spine)@H_403_5@
$(call import-editor@H_403_5@-support@H_403_5@/cocostudio@H_403_5@)@H_403_5@
$(call import-network@H_403_5@)@H_403_5@
$(call import-extensions@H_403_5@)@H_403_5@