Android.mk高级写法
转:http://blog.csdn.net/langresser_king/article/details/8275291
原本只是想记录一些常用的使用技巧,但是越写越得意(>_<),忍不住想要做出一份相对完善的说明文档,以供大家研究探讨。
写这篇文章的起因当然是实际工程需要,在搭建一个网游的android客户端时遇到种种恶心的问题,比如文件过多导致"Argument list too long" 的错误,又比如增加和删除文件时都需要维护好Android.mk配置,虽然可以通过写个脚本自动生成android.mk,但是终归不是很漂亮的解决方 案。通过本文所提到的几个方法,可以使Android.mk变得十分简洁,减少增加和删减工程文件时对Android.mk的修改,工程文件数目较多时会 非常实用。
我先附上修改后的cocos2d-x工程配置(在本文的最后,我还会附上原始的配置,有兴趣的同学可以对比下看看),然后在此基础上逐一说明:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_MODULE := cocos2dx_static
LOCAL_MODULE_FILENAME := libcocos2d # 定义查找所有cpp文件的宏
define all-cpp-files-under
$(patsubst ./%,%, $(shell find $(LOCAL_PATH) -name "platform" -prune -o -name "*.cpp" -and -not -name ".*"))
endef define all-subdir-cpp-files
$(call all-cpp-files-under,.)
endef # 定义查找所有c文件的宏,android有默认定义,此处可酌情省略
define all-c-files-under
$(patsubst ./%,%, $(shell find $(LOCAL_PATH) -name "platform" -prune -o -name "*.c" -and -not -name ".*"))
endef define all-subdir-c-files
$(call all-c-files-under,.)
endef # 通过查找获取所有工程文件列表
CPP_FILE_LIST := $(call all-subdir-cpp-files) \
$(wildcard $(LOCAL_PATH)/platform/*.cpp) \
$(wildcard $(LOCAL_PATH)/platform/android/*.cpp) \
$(wildcard $(LOCAL_PATH)/platform/android/jni/*.cpp)
C_FILE_LIST := $(call all-subdir-c-files) #4 加入工程文件,之所以不直接加是需要进行一个LOCAL_PATH的替换
LOCAL_SRC_FILES := $(CPP_FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_SRC_FILES += $(C_FILE_LIST:$(LOCAL_PATH)/%=%) LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/kazmath/include \
$(LOCAL_PATH)/platform/android LOCAL_EXPORT_LDLIBS := -llog\
-lz \
-lGLESv2 #5 加入头文件
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/kazmath/include \
$(LOCAL_PATH)/platform/android #6 需要链接的系统默认库
LOCAL_LDLIBS := -lGLESv2 \
-lEGL \
-llog \
-lz #7 加入静态库,加了LOCAL_WHOLE_STATIC_LIBRARIES代表编译器会将静态库完整链接而不会进行删减优化
LOCAL_WHOLE_STATIC_LIBRARIES := cocos_libpng_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_jpeg_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_libxml2_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_libtiff_static #8 预编译宏
# define the macro to compile through support/zip_support/ioapi.c
LOCAL_CFLAGS := -DUSE_FILE32API
LOCAL_EXPORT_CFLAGS := -DUSE_FILE32API #9 声明生成静态库
include $(BUILD_STATIC_LIBRARY) #10 添加外部导入库目录
$(call import-add-path,$(LOCAL_PATH)) #11 添加导入库(基于上一行添加的导入库目录)
$(call import-module,platform/third_party/android/prebuilt/libjpeg)
$(call import-module,platform/third_party/android/prebuilt/libpng)
$(call import-module,platform/third_party/android/prebuilt/libxml2)
$(call import-module,platform/third_party/android/prebuilt/libtiff)
首先是自动遍历整个工程文件的方法,当解决这个问题,我们的目的也就实现了一大半。我先介绍makefile里面的三个常用命令:
1、wildcard : 扩展通配符,用于查找一个目录下的所有符合条件的文件
2、notdir : 去除路径,仅保留文件名
3、patsubst :替换通配符,也可以是任意文本替换
#1 #2这两处我定义了两个宏,用于遍历整个工程的cpp和c文件。
$(patsubst ./%,%, $(shell find $(LOCAL_PATH) -name "platform" -prune -o -name "*.c" -and -not -name ".*"))
如上文所 说,patsubst是文本替换,也就是把$(shell....)所返回的查找到的所有文件名去除掉开头的"./",具体替换原因我们下文会说明。 $(shell...)会执行任意的shell命令(如果是在windows下,就一定要用cygwin来执行ndk-build)。
find可以查找指定目录下的所有符合条件的文件。find后面跟查找目录,这里就是Android.mk所在目录。需要特别注意后面的 -name "platform" -prune这个参数,它可以过滤掉特定文件夹("platform"),使用时要先通过-name把文件夹名字传递过去,然后添加-prune,如果没 有需要过滤的文件夹,就不需要这个参数了。 -o可以指定输出,如果使用了-prune就一定要有这个参数,表示在过滤结果的基础上进行查找。 最后跟查找的判定式,示例中的判定式代表查找所有.c文件但是忽略以.开头的文件(通常是系统文件或隐藏文件)。 find命令是实现文件遍历的基础。
#3处我们定义了一个宏代表文件列表
CPP_FILE_LIST := $(call all-subdir-cpp-files) \
$(wildcard $(LOCAL_PATH)/platform/*.cpp) \
$(wildcard $(LOCAL_PATH)/platform/android/*.cpp) \
$(wildcard $(LOCAL_PATH)/platform/android/jni/*.cpp)
C_FILE_LIST := $(call all-subdir-c-files)
调用 $(call all-subdir-cpp-files) 返回了所有cpp文件列表,但是由于我们有指定忽略platform目录的文件,所以需要在后面把这个目录下android平台相关的文件加进来。
$(wildcard $(LOCAL_PATH)/platform/*.cpp)
这个我们一开始有介绍,就是遍历某一目录下的所有特定扩展名的文件。这个命令的缺点是不支持递归目录遍历(否则也就不需要我们前面写一大堆东西了),不过如果你的工程没有太多目录的话,可以直接使用这个。
#4处正式把文件加入到android工程中
LOCAL_SRC_FILES := $(CPP_FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_SRC_FILES += $(C_FILE_LIST:$(LOCAL_PATH)/%=%)
$(CPP_FILE_LIST:$(LOCAL_PATH)/%=%) 这个又是一个文本替换技巧。意思是,把CPP_FILE_LIST里面的所有$(LOCAL_PATH)/去掉。之所以有这样的替换是因为LOCAL_SRC_FILES已经包含了LOCAL_PATH,其文件名应该是相对于Android.mk的相对路径。如果SRC_FILES里面还包含LOCAL_PATH的路径那就出错了。同样这也是我们在#1 #2处需要将查找到的文件名中的"./"去除掉的原因。
#5~#9可以直接看注释,没有什么需要特别说明的。
我们再重点说下#10 #11,也就是导入库的使用。
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_jpeg_static
#LOCAL_STATIC_LIBRARIES += cocos_jpeg_static
$(call import-module,platform/third_party/android/prebuilt/libjpeg)
加入静态 库(第一行和第二行看实际情况使用,差别不大),然后使用call import-module引入导入库。在编译我们这个Android.mk模块时编译器会自动查找并编译libjpeg模块。通过使用导入库可以更加清 晰和方便的复用现有库,或者像我一样把一个大的工程拆分成多个子模块,然后再链接到一起。这样还有一个附带的好处是,当我们修改Android.mk文件 时,本文件的代码都会重新编译,但是导入库引入的模块不会。如果我们的工程很大,那么使用导入库后就可以避免修改一下配置就重新编译整个工程的情况。
prebuilt库的使用:
目的:复用没有源代码的静态库或动态库。
方式:新建一个文件夹如libpng,将头文件放到里面的include目录,.a静态库放到里面的libs目录,新建一个Android.mk其内容如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cocos_libpng_static
LOCAL_MODULE_FILENAME := png
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libpng.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
重点有两个LOCAL_MODULE是prebuilt库的名字,外部使用时添加的就是这个名字, LOCAL_EXPORT_C_INCLUDES是导出头文件,方便外部头文件包含。
外部使用时像普通的导入库一样使用,再次强调名字一定要一致,否则prebuilt库无法正确导入,就会出现头文件找不到或者是链接错误:
LOCAL_WHOLE_STATIC_LIBRARIES := cocos_libpng_static
$(call import-module,cocos2dx/platform/third_party/android/prebuilt/libpng)
Android.mk高级写法的更多相关文章
- cocos2d-x 3.0 引用第三方库 及编译成apk时android mk文件写法
cocos2d-x 3.0 中.假设你须要使用CocosStudio.Extensions扩展库 等等.都须要自己手动加入. 加入过程例如以下:(比方说如今我要加入libExtensions,libC ...
- android编译系统的makefile文件Android.mk写法
Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件.由于一般情况下Android.mk和需要编译的源文件在同一目录下,宏函数“my-dir”右编译系统提供的,用于返回当前路径 ...
- android编译系统的makefile文件Android.mk写法如下
(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件.由于一般情况下Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式:LOCAL_PATH:=$(c ...
- Android.mk编译的写法
更多Android.mk的 用法见 :http://blog.csdn.net/fengbingchun/article/details/38705519 如何修改Android.mk 为Androi ...
- Android.mk走读与Cmake配置
Android.mk认识: 在上一次[https://www.cnblogs.com/webor2006/p/9946061.html]中学会了用NDK提供的交叉编译工程编译成Android能运行的可 ...
- Android.mk 文件语法详解
0. Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build Syst ...
- Android.mk相关知识
Android.mk是Android提供的一种makefile文件,用来指定诸如编译生成so库名.引用的头文件目录.需要编译的.c/.cpp文件和.a静态库文件等.要掌握jni,就必须熟练掌握Andr ...
- Android.mk的用法和基础【转】
一个Android.mk file用来向编译系统描述你的源代码.具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次.你可以在每一个Android.mk file中定义一个 ...
- Android.mk详解
Android.mk是Android提供的一种makefile文件,用来指定诸如编译生成so库名.引用的头文件目录.需要编译的.c/.cpp文件和.a静态库文件等.要掌握jni,就必须熟练掌握Andr ...
随机推荐
- IT技术需求建立时需考虑的因素
2012-11-13 内容存档在evernote,笔记名"IT技术需求建立时需考虑的因素"
- windbg dds、dps、dqs
dds.dps和dqs命令显示给定范围内存的内容,它们是把内存区域转储出来,并把内存中每个元素都视为一个符号对其进行解析,dds是四字节视为一个符号,dqs是每8字节视为一个符号,dps是根据当前处理 ...
- 【Algorithm】插入排序
一. 算法描述 插入排序具体算法描述如下: 从第一个元素开始,该元素可以认为已经被排序 取出下一个元素,在已经排序的元素序列中从后向前扫描 如果该元素(已排序)大于新元素,将该元素移到下一位置 重复步 ...
- 如何在osx的终端下使用字典
因为各种原因我经常要在osx上查英文单词,在osx系统下,查字典其实是一件非常优雅的事情,三指轻触,简单快速.在terminal中其实也是这样,3指轻触需要查询的单词,释义一触即发,用户体验非常好.不 ...
- Shell脚本:向磁盘中批量写入数据
一.关于本文 工作要做的监控系统需要监控磁盘空间的使用率并报警.在测试这个功能的时候需要模拟两个场景:一是磁盘空间不断增长超过设定的阈值时,需要触发报警机制:二是磁盘空间降落到低于报警阈值的时候,不再 ...
- Hive实现从表中随机抽样得到一个不重复的数据样本
select a.* from ( select a.*,rand(12345) as random from tripdata a ) a where random between 0 and 0. ...
- [转]OkHttp3 最有营养的初级教程
一.前言 自从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp,而在Android6.0之后的SDK中google更是移除了对于HttpCl ...
- Universal USB Installer集开源软件之佳作
有机会下载一份uui的源代码,翻看了一下,呵呵,有意思,几乎是一个开源软件的大杂烩,忽然,恍然大悟,原来,作者才是开源软件精神的代言人,不重复制造轮子的践行者啊. uui网址:https://www. ...
- android 判断点击的位置是不是在指定的view上
private boolean inRangeOfView(View view, MotionEvent ev){ int[] location = new int[2]; view.getLocat ...
- apache做转发
一台WIN服务器,上面主要装了WAMP程序来运行PHP 的相关东西,现在在机子里的IIS建立了一个ASP.NET站点,访问端口88,服务器上可以:http://127.0.0.1:88来访问.NET网 ...