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 ...
随机推荐
- JSONObject.parseObject(jsonStr);和JSONObject.fromObject(jsonStr);
虽然都是返回JSONObject,但是 JSONObject.parseObject(jsonStr);这个方法需要导入import com.alibaba.fastjson.JSONObject; ...
- Nginx 和 PHP 的两种部署方式比较
2种部署方式简介 第一种 前置1台nginx服务器做HTTP反向代理和负载均衡 后面多态服务器部署Nginx Web服务和php-fpm提供的fast cgi服务 第二种 前置1台nginx服务器做W ...
- 细说PHP中strlen和mb_strlen的区别(转)
在PHP中,strlen与mb_strlen是求字符串长度的函数,但是对于一些初学者来说,如果不看手册,也许不太清楚其中的区别.下面通过例子,讲解这两者之间的区别. 先看例子: <?php // ...
- 【IL】IL入门
1.IL基本介绍 1.1 CLR介绍 在介绍IL之前,先说一说CLR.CLR的全称Commen Language Runtime 公共语言运行时.因为CLR的存在,使得多语言开发成为可能.下面给出一张 ...
- Linux下面安装和配置MySQL
如何从MySQL官方Yum仓库安装MySQL5.6 首先我们需要从MySQL开发者网站下载Yum仓库文件 Download MySQL Yum Repository 从上面的连接地址下载:Red Ha ...
- aaronyang的百度地图API之LBS云与.NET开发 Javascript API 2.0【基本地图的操作】
为了更简单的演示,我们创建个.NET的ASP.NET MVC4项目 好了,上面都是后话,POI说白了,就是你的用户的数据,很多数据,不过没关系,因为你的数据如果存在百度的LBS云上,那么大数据你就不用 ...
- MongoDB学习笔记(5)--document
MongoDB 插入文档 本章节中我们将向大家介绍如何将数据插入到MongoDB的集合中. 文档的数据结构和JSON基本一样. 所有存储在集合中的数据都是BSON格式. BSON是一种类json的一种 ...
- c2java select algorithm
对于非常多应用来说,随机算法是最简单的或者最快的.既简单又快的有没有呢? 那须要深刻的洞察力或者革命性的突破. 什么是随机算法 随机算法与确定算法差别是:它还接收输入随机比特流来做随机决策. 对于同一 ...
- [转]八幅漫画理解使用JSON Web Token设计单点登录系统
上次在<JSON Web Token - 在Web应用间安全地传递信息>中我提到了JSON Web Token可以用来设计单点登录系统.我尝试用八幅漫画先让大家理解如何设计正常的用户认证系 ...
- [转]如何在 Git 里撤销(几乎)任何操作
任何版本控制系统的一个最有的用特性就是“撤销 (undo)”你的错误操作的能力.在 Git 里,“撤销” 蕴含了不少略有差别的功能. 当你进行一次新的提交的时候,Git 会保存你代码库在那个特定时间点 ...