希望看原文的请移步:[原创]编写Android.mk中的LOCAL_SRC_FILES的终极技巧

问题的引入

在使用NDK编译C/C++项目的过程中,免不了要编写Android.mk文件,其中最重要的就是LOCAL_SRC_FILES源文件列表. 考虑有如下源文件分布的情况:

cpp文件全部位于android项目下的jni文件夹下,结构如下
    jni
|---.cpp
|---.cpp
|---Android.mk
|---Application.mk
|---ndk_test.cpp
|---src
| |---core
| | |---core1.cpp
| | |---core2.cpp
| |---src1.cpp
| |---src2.cpp
 

按照通常的写法,在android.mk中,应该写入

LOCAL_SRC_FILES := ndk_test.cpp \
1.cpp \
2.cpp \
src/src1.cpp \
src/src2.cpp \
src/core/core1.cpp \
src/core/core2.cpp

繁琐不堪!

初步解法:一句话引入单个目录(不包括子目录)下的所有cpp源文件

继续上面的情况为例,我可以这样写

MY_CPP_LIST := $(wildcard $(LOCAL_PATH)/*.cpp)
MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/*.cpp)
MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/core/*.cpp) LOCAL_SRC_FILES := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%)

问题解决. 简单解释一下上面的几句话

  1. 1、MY_CPP_LIST := $(wildcard $(LOCAL_PATH)/*.cpp),这句话的意思是使用wildcard函数获取$(LOCAL_PATH)目录也就是jni目录下的所有后缀名为cpp的文件,并把结果放到变量MY_CPP_LIST里.
  2. 我们知道$(LOCAL_PATH)指的是当前Android.mk文件所在目录,所以通过这句话,MY_CPP_LIST中的值应该是jni/1.cpp jni/2.cpp jni/ndk_test.cpp.
  3. 2、MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/*.cpp), 获取jni/src目录下的源文件,并追加到变量MY_CPP_LIST
  4. 3、MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/core/*.cpp),同上,获取jni/src/core目录下的源文件
  5. 4、通过以上几步,得到MY_CPP_LIST中内容是:jni/1.cpp jni/2.cpp   jni/ndk_test.cpp   jni/src/src1.cpp  jni/src/src2.cpp  jni/src/core/core1.cpp      jni/src/core/core2.cpp
    1. 5、LOCAL_SRC_FILES := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%),前面我们获取的文件都是以jni开头的,而真正编译所需要的文件都应该是直接从jni目录开始的,所以我们使用模式替换把所有文件名前面的jni/去掉.

    这里我解释一下$(MY_CPP_LIST:$(LOCAL_PATH)/%=%)的语法含义,它的意思是对MY_CPP_LIST中每一项,应用冒号后面的规则,规则是什么呢?规则是$(LOCAL_PATH)/%=%,意思是,查找所有$(LOCAL_PATH)/开头的项,并截取后面部分

    最后一句话也可以使用subst函数写成:

    #替换每一项中的 "$(LOCAL_PATH)/" 为 ""(空)
    LOCAL_SRC_FILES := $(subst $(LOCAL_PATH)/, , $(MY_CPP_LIST))

    或使用patsubst函数写成

    #同模式替换,这里使用patsubst函数
    LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%, %, $(MY_CPP_LIST))

    具体语法请参考:Functions for String Substitution and Analysis

    实际使用中,可以把代码放在jni目录以外的目录里,这时只要修改wildcard函数里的相对路径就可以了,甚至也可以使用绝对路径,只要你愿意.

    以上代码已经足以应付大多数情况了,不过人的懒惰是无极限的,像上面的情况我的所有源文件都在jni目录下,为什么还要把每个子目录都写一行呢,不太优雅呀,最好能写一句话把jni目录下的所有源文件都引入.

  6. 进阶:引入单个目录(包括子目录)下的所有cpp源文件

    为了达到引入目录下的所有源文件,包括子目录这个目标,我在android.mk中这样写

    #声明一个变量MY_CPP_PATH表示源码目录
    MY_CPP_PATH := $(LOCAL_PATH)/ #获取目录下的所有文件
    My_All_Files := $(shell find $(MY_CPP_PATH)/.)
    My_All_Files := $(My_All_Files:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%) #从My_All_Files中再次提取所有的cpp文件,这里也可以使用filter函数
    MY_CPP_LIST := $(foreach c_file,$(My_All_Files), $(wildcard $(c_file)/*.cpp) )
    MY_CPP_LIST := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%) LOCAL_SRC_FILES := $(MY_CPP_LIST)
     

    通过以上几行,成功得到了jni目录包含它的子目录下的所有cpp源文件,并正确编译.实际使用中,代码不一定存放在jni目录下,修改MY_CPP_PATH就可以了,注意:MY_CPP_PATH最好使用以$(LOCAL_PATH)开头的相对目录

    这种写法极大的方便了项目的开发,以前在源码目录下新建cpp源文件,新建目录都不需要再来修改android.mk文件了.

    还有一个问题,上面代码里只是引入cpp文件,如果源码文件夹下还有c文件呢,怎么办?再多写几行?

  7. 进阶2.0:引入单个目录(包括子目录)下的所有*.cpp和*.c源文件

    这里,我直接给出代码

    MY_CPP_PATH  := $(LOCAL_PATH)/
    My_All_Files := $(shell find $(MY_CPP_PATH)/.)
    My_All_Files := $(My_All_Files:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%)
    MY_CPP_LIST := $(filter %.cpp %.c,$(My_All_Files))
    MY_CPP_LIST := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%) LOCAL_SRC_FILES := $(MY_CPP_LIST)

    代码中用到了filter函数.

    还不满足?如果项目的源码有多个目录放在不同的地方,而且有多个后缀,怎么办?

    终极进阶:引入多个目录(包括子目录)下的多个后缀名的源文件

    上代码(2013年10月9日修正):

    # 扫描目录下的所有源文件
    MY_FILES_PATH := $(LOCAL_PATH) \
    $(LOCAL_PATH)/../../Classes MY_FILES_SUFFIX := %.cpp %.c %.cc My_All_Files := $(foreach src_path,$(MY_FILES_PATH), $(shell find $(src_path) -type f) )
    My_All_Files := $(My_All_Files:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%)
    MY_SRC_LIST := $(filter $(MY_FILES_SUFFIX),$(My_All_Files))
    MY_SRC_LIST := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)
    LOCAL_SRC_FILES := $(MY_SRC_LIST)

    以上代码中,变量MY_FILES_PATH保存源文件所在目录,MY_FILES_SUFFIX保存源文件的后缀名

[转]编写Android.mk中的LOCAL_SRC_FILES的终极技巧的更多相关文章

  1. 编写Android.mk中的LOCAL_SRC_FILES的终极技巧(转)

    转自:http://blog.csdn.net/fu_zk/article/details/12836431 问题的引入 在使用NDK编译C/C++项目的过程中,免不了要编写Android.mk文件, ...

  2. 【转】Update: Android.mk 中的 LOCAL_SRC_FILES, LOCAL_C_INCLUDES

    看原文请移步:Update: Android.mk 中的 LOCAL_SRC_FILES, LOCAL_C_INCLUDES 我在先前的两篇post 编写Android.mk中的LOCAL_SRC_F ...

  3. [转]编写 android.mk 中 LOCAL_C_INCLUDES 的技巧

    看原文请移步:编写 android.mk 中 LOCAL_C_INCLUDES 的技巧 在编写android.mk的过程中,免不了要修改LOCAL_C_INCLUDES来设置头文件的include目录 ...

  4. Android.mk中的经常使用语法

    Android.mk编译文件是用来向Android NDK描写叙述你的C,C++源码文件的, 今天查了一些经常使用的的语法. 一 概述: 一个Android.mk文件用来向编译系统描写叙述你的源码. ...

  5. Android.mk中添加宏定义

    在Boardconfig.mk 中添加一个 IS_FLAG := true 由于Boardconfig.mk和各目录的Android.mk是相互关联的 所以我们可以在Android.mk 中添加 一个 ...

  6. Android.mk中添加宏定义【转】

    本文转载自:http://blog.csdn.net/huangyabin001/article/details/38302021 在Boardconfig.mk 中添加一个 IS_FLAG := t ...

  7. Android.mk 中常用“LOCAL_” 变量

    编写模块的编译文件,实际就是定义一系列以“LOCAL_”开头的编译变量,因此我们有必要弄明白这些变量的具体含义.下面是一些经常使用的LOCAL_编译变量的说明: 变量名 说明 LOCAL_ASSET_ ...

  8. Android.mk中引用第3方动态库

    Android.mk 文件内容: LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOC ...

  9. Android.mk中call all-subdir-makefiles和call all-makefiles-under,$(LOCAL_PATH)的区别(转载)

    转自:http://blog.csdn.net/jackyu613/article/details/5949324 在写Android.mk文件时,call all-subdir-makefiles和 ...

随机推荐

  1. Websocket——Websocket原理

    偶然在知乎上看到一篇回帖,瞬间认为之前看的那么多资料都不及这一篇回帖让我对 websocket 的认识深刻有木有.所以转到我博客里,分享一下.比較喜欢看这样的博客,读起来非常轻松.不枯燥,没有布道师的 ...

  2. AutoResponder Reference

    Fiddler's AutoResponder tab allows you to return files from your local disk instead of transmitting ...

  3. 修复eclipse build-helper-maven-plugin 异常

    安装 help --> install new http://repo1.maven.org/maven2/.m2e/connectors/m2eclipse-buildhelper/0.15. ...

  4. 【BIRT】使用rptlibrary设置统一数据源

    在使用birt开发报表的过程中我们通常会发现,如果直接在报表中写死数据源的话,那么之后如果数据库服务器发生变更,那么所有的报表都得一一去修改数据源 这是一个相当耗时间的过程. 1.首先新建librar ...

  5. 1、创建一个空白的xls和xlsx文件

    1.创建一个空白的xls文件 Step1:先引入库NPOI.dll文件 Step2: ①:实例化一个workbook,实为在内存表中创建一个xls文件 NPOI.HSSF.UserModel.HSSF ...

  6. 如何在 CentOS 7 中安装、配置和安全加固 FTP 服务

    步骤 1:安装 FTP 服务器 1. 安装 vsftpd 服务器很直接,只要在终端运行下面的命令. # yum install vsftpd 2. 安装完成后,服务先是被禁用的,因此我们需要手动启动, ...

  7. 在ListView的右边添加字母列表

    在ListView的右边添加字母列表,点击某个字母时,列表就滚动到预期位置. <!-- 数字和字母栏在标题栏下边并且停靠在右边 --> <com.txrj.sms.component ...

  8. eclipse里面的时间错误,比电脑系统时间慢了8个小时

    eclipse里面的时间错误,比电脑系统时间慢了8个小时 解决办法: 打开<eclipse安装目录>/eclipse.ini文件 在文件末尾追加 -Duser.timezone=Asia/ ...

  9. PHP读取大文件的几种方法

    场景:PHP读取超大文件,例如1G的日志文件,我这里使用的是400M的access.log文件 1.使用file直接读取 <?php $starttime=microtime_float(); ...

  10. beanUtils的用法

    举例1:使用BeanUtils工具封装用户提交的数据. public static void main(String[] args)throws Exception { // 模拟用户的输入的数据如下 ...