编写Android.mk中的LOCAL_SRC_FILES的终极技巧

Android.mk 文件使用解析 和你一起终身学习,这里是程序员Android经典好文推荐,通过阅读本文,您将收获以下知识点:一、Android.mk 简介二、Android.mk 的基本格式三、Android.mk 深入学习一四、 Android.mk 深入学习二五、 Android.mk 深入学习三六、 Android.mk 判断语句七、参考文献一 、Android.mk 简介Android.mk 是Android 提供的一种... 阅读详情
转载: http://blog.youkuaiyun.com/xiangzilv1987/article/details/16805701

问题的引入

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

cpp文件全部位于android项目下的jni文件夹下,结构如下

    jni    
     |---1.cpp
     |---2.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. MY_CPP_LIST := $(wildcard $(LOCAL_PATH)/*.cpp),这句话的意思是使用wildcard函数获取$(LOCAL_PATH)目录也就是jni目录下的所有后缀名为cpp的文件,并把结果放到变量MY_CPP_LIST里.我们知道$(LOCAL_PATH)指的是当前Android.mk文件所在目录,所以通过这句话,MY_CPP_LIST中的值应该是jni/1.cpp jni/2.cpp jni/ndk_test.cpp.
  2. MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/*.cpp), 获取jni/src目录下的源文件,并追加到变量MY_CPP_LIST里
  3. MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/core/*.cpp),同上,获取jni/src/core目录下的源文件
  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
  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目录下的所有源文件都引入.

进阶:引入单个目录(包括子目录)下的所有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文件呢,怎么办?再多写几行?

进阶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保存源文件的后缀名

原创文章,转载请注明,谢谢!

PS:如何debug 一个android.mk文件

有一个办法,那就是在编译过程输出android.mk文件中变量的值,就可以观察分析问题所在了,使用代码

$(warning $(LOCAL_SRC_FILES))

就可以在编译过程中从终端窗口中观察到变量LOCAL_SRC_FILES的值

Android源代码定制:MK文件执行顺序|属性覆盖 在本文中介绍了Android源代码定制的一些机制和工具,包括: 介绍了mk文件的结构和语法,以及如何确定mk文件的执行顺序。 介绍了属性的类型和赋值方式,以及如何覆盖属性的值。 阅读详情

相关推荐

OpenResty无损升级内嵌nginx版本0DAY漏洞

OpenResty无损升级内嵌nginx版本,nginx

qq1071643762的博客 6904

cocos2d-x 编写Android.mk中的LOCAL_SRC_FILES的终极技巧

问题的引入 在使用NDK编译C/C++项目的过程中,免不了要编写Android.mk文件,其中最重要的就是LOCAL_SRC_FILES源文件列表. 考虑有如下源文件分布的情况: cpp文件全部位于android项目下的jni文件夹下,结构如下 jni |---1.cpp |---2.cpp |---Android.mk |---App

郑州|boy的专栏 3484

别再为reg2icg的setup违例头疼了!手把手教你用ICC2/Innovus这3招搞定(附实战数据对比)

本文详细介绍了在ICC2/Innovus中解决reg2icg的setup违例的三种高效方法,包括早期时钟树预估、精准控制时钟延迟与门控检查以及ICG专用优化选项组合。通过实战数据对比,展示了不同策略的效果差异,帮助工程师快速优化时序路径,提升芯片性能。

weixin_42569329的博客 407

Android.mk里的LOCAL_SRC_FILES

LOCAL_SRC_FILES 变量代表需要编译的文件,all-subdir-java-files 函数返回 LOCAL_PATH 子目录的所有 java文件。几个常用的获取源文件的方法:包名之外的路径(com之前的):获取指定目录下的所有 Java 文件。:获取指定目录下的所有 AIDL 文件。:获取指定目录下的所有 C 语言文件。:获取指定目录下的所有 Make 文件。

xiaowang_lj的博客 1608

基于ROS的室内移动机器人自主导航技术

随着机器人技术的发展,近些年来室内移动机器人的研究热度越来越高。本文主要利用ROS操作系统对室内移动机器人的建图定位与自主导航关键技术进行研究。 ROS是目前开发较为完整具有广阔应用前景的开源机器人操作系统,具有分布式、模块化、代码复用等优良特点。同时ROS还提供了许多开源库,在这些库的基础之上研究同时定位与地图构建和机器人自主导航技术可以节省大量时间。 ORB-SLAM2是比较优秀的视觉SLAM算法之一,它具有计算量比较小、能够实时运行等优点。在介绍ORB-SLAM2的框架之前,首先会介绍视觉SLAM的一

weixin_44553616的博客 1909

蜻蜓fm爬虫python

本文介绍了一个用于下载蜻蜓FM音频书籍的Python脚本实现。该脚本主要功能包括:1)通过账号密码登录获取认证信息;2)从目标书籍主页提取版本信息;3)获取书籍节目总数和分页信息;4)生成节目下载链接(使用HMAC-MD5加密算法生成请求签名);5)下载音频文件并保存。脚本采用多种反爬措施:设置User-Agent模拟浏览器行为、使用动态时间戳、HMAC-MD5签名验证等,有效规避简单的反爬机制。整个流程包括登录认证、获取书籍信息、生成下载链接和保存音频文件四个步骤,实现自动化批量下载功能。

野猫炫的博客 912

深入浅出Android makefile(3)--LOCAL_SRC_FILES

讨论完LOCAL_PATH,我们紧接着来看看LOCAL_SRC_FILES。 一、LOCAL_SRC_FILES LOCAL_SRC_FILES := acp.c LOCAL_SRC_FILES变量的意思见名知意,很明显是用来记录当前模块的源文件列表的一个变量。 这里是他的赋值,我们下面来看看他的使用的...

iteye_13928的博客 686

将Windbg附加到软件进程上排查异常闪退的问题

使用Windbg和Process Explorer排查因为内存泄漏导致的软件异常闪退问题。

dvlinker的技术专栏 1万+

【安卓】编写 Android.mk 中的 LOCAL_SRC_FILES 的终极技巧*

链接: 问题的引入 在使用NDK编译C/C++项目的过程中,免不了要编写Android.mk文件,其中最重要的就是LOCAL_SRC_FILES源文件列表. 考虑有如下源文件分布的情况: cpp文件全部位于android项目下的jni文件夹下,结构如下 jni |---1.cpp |---2.cpp |---Android.mk

アーキテクトがしたい! 635

【2024遥感应用组一等奖】基于时空融合和水量平衡法的若尔盖高原水源涵养功能评价

考虑到水源涵养的概念和尺度特征、数据的可获得性、模型的模拟精度等,构建了一种基于遥感、气象和水量平衡原理的草原湿地水源涵养评价方法,估算若尔盖湿地近23年(2000-2022)来的水源涵养量。若尔盖湿地是我国黄河源区的重要水源地,所以本研究以若尔盖湿地的水源涵养功能评估为科学问题,基于遥感数据、GIS数据等,利用水量平衡原理,发展计算简单、便捷、数据易获取的“水源涵养估算方法”,科学估算若尔盖湿地水源涵养服务量,探究其时空动态变化趋势及其影响因素;公式中,Z1和Z2为两个不同高度面的高度,u为摩擦速率;

JData_Engineer的博客 239

大数据知识面试题-通用(2026版)

序列号 内容 链接 1 大数据知识面试题-通用(2022版) 待续… 2 大数据知识面试题-Hadoop(2022版) 待续… 3 大数据知识面试题-MapReduce和yarn(2022版) 待续… 4 大数据知识面试题-Zookeepr (2022版) 待续… 5 大数据知识面试题-Hive (2022版) 待续… 6 大数据知识面试题-Flume(2022版) 待续… 7 大数据知识面试题-Hbase(2022版) 待续… 8 大数据知识面试题-sqoop(....

拉格朗日的学习笔记 2万+

c语言mk文件,[原创]编写Android.mk中的LOCAL_SRC_FILES的终极技巧

问题的引入在使用NDK编译C/C++项目的过程中,免不了要编写Android.mk文件,其中最重要的就是LOCAL_SRC_FILES源文件列表.考虑有如下源文件分布的情况:cpp文件全部位于android项目下的jni文件夹下,结构如下jni|---1.cpp|---2.cpp|---Android.mk|---Application.mk|---ndk_test.cpp|---src| ...

weixin_32823993的博客 840

《UDS/OBD诊断需求编辑工具》总目录

目录 1 基于CANdela Studio编辑CDD诊断描述文件 2 基于ODX Studio编辑ODX/PDX文件 2.1 编辑ODX-D诊断描述文件 2.2 编辑ODX-F刷写软件 该专栏主要负责介绍CANdela Studio和ODX Studio编辑CDD/ODX/PDX诊断描述文件。 1 基于CANdela Studio编辑CDD诊断描述文件 2 基于ODX Studio编辑ODX/PDX文件 【ODX介绍 】-1- 标准梳理 【ODX介绍】 -2-如何手..

「汽车电子助手」的博客 1万+
上一篇: Android.mk多级目录源码的编写
下一篇: Android Sensor (g-sensor) 系统源码分析
shell812
博客等级 码龄18年 202粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值