LOCAL_WHOLE_STATIC_LIBRARIES与LOCAL_STATIC_LIBRARIES的区别
在分析Jelly Bean Audio Subsystem的时候,发现HAL层的库audio_policy.xxx.so与其依赖的静态库libaudiopolicy_legacy.a都有audio_policy_hal.cpp这个源文件而且两者都定义了一个HMI。当调用者引用HMI的时候,调用的究竟是哪个呢?
首先看audio_policy.xxx.so的Android.mk文件,在定义编译audio_policy.xxx.so的段落里面有这么一句:
LOCAL_STATIC_LIBRARIES := \
libaudiohw_legacy \
libmedia_helper \
libaudiopolicy_legacy
说明libaudiopolicy_legacy是以静态库的形式为audio_policy.xxx.so所用,而在通用的audio_policy库(也可以说是谷歌提供给厂商参考用的policy库)audio_policy.default.so的库里面是这么用的:
LOCAL_WHOLE_STATIC_LIBRARIES := \
libaudiopolicy_legacy
而audio_policy.default.so的源码里面就没有audio_policy_hal.cpp这个源文件,所以玄机应该就在LOCAL_WHOLE_STATIC_LIBRARIES和LOCAL_STATIC_LIBRARIES这两个宏的差异上面。先看下谷歌在build/core/build-system.html里面是怎么说的:
LOCAL_STATIC_LIBRARIES
These are the static libraries that you want to include in your module. Mostly, we use shared libraries, but there are a couple of places, like executables in sbin and host executables where we use static libraries instead.
LOCAL_WHOLE_STATIC_LIBRARIES
These are the static libraries that you want to include in your module without allowing the linker to remove dead code from them. This is mostly useful if you want to add a static library to a shared library and have the static library's content exposed from the shared library.
总的来说LOCAL_WHOLE_STATIC_LIBRARIES在连接静态连接库的时候不会移除"daed code",何谓dead code呢,就是调用者模块永远都不会用到的代码段和变量,下面用几个小源码来说明。
Android.mk如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_SRC_FILES := \
libstone_1.cpp LOCAL_MODULE := libstone_1
LOCAL_MODULE_TAGS := optional include $(BUILD_STATIC_LIBRARY) # =========================================
include $(CLEAR_VARS) LOCAL_SRC_FILES := \
libstone_2.cpp LOCAL_STATIC_LIBRARIES := libstone_1
#<span style="color:#ff0000;"> LOCAL_WHOLE_STATIC_LIBRARIES := libstone_1</span>
LOCAL_MODULE := libstone_2
LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY)
静态库源文件(libstone_1.cpp):
char hello[] = "this is a string in libstone_1";
char str_2[] = "non static string 1";
char str_3[] = "non static string 2";
void func_1(){hello[]+=;}
调用者源文件(libstone_2.cpp):
char hello[] = "this is a string in libstone_2";
case 1,按照上述的代码make之后,libstone_1的所有东西都没有被连接到动态库libstone_2里面:
readelf -Ws system/lib/libstone_2.so
Symbol table '.dynsym' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00002000 31 OBJECT GLOBAL DEFAULT 13 hello2
2: 000002e8 12 FUNC GLOBAL DEFAULT 7 __on_dlclose
3: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_finalize
4: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_unwind_cpp_pr0
5: 00002020 0 NOTYPE GLOBAL DEFAULT 14 __dso_handle
6: 00001ee4 0 NOTYPE GLOBAL DEFAULT 9 __INIT_ARRAY__
7: 00001eec 0 NOTYPE GLOBAL DEFAULT 10 __FINI_ARRAY__
8: 0000201f 0 NOTYPE GLOBAL DEFAULT ABS _edata
9: 0000201f 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
10: 00002030 0 NOTYPE GLOBAL DEFAULT ABS _end
case 2,修改Android.mk使用LOCAL_WHOLE_STATIC_LIBRARIES 宏,这个时候libstone_2.cpp中的hello要改成hello2,因为libstone_1里面的东西全部链接进来了:
readelf -Ws system/lib/libstone_2.so
Symbol table '.dynsym' contains 16 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000037d 20 FUNC GLOBAL DEFAULT 7 _Z6func_3v
2: 0000201f 31 OBJECT GLOBAL DEFAULT 13 hello
3: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_unwind_cpp_pr0
4: 00002000 31 OBJECT GLOBAL DEFAULT 13 hello2
5: 00000390 12 FUNC GLOBAL DEFAULT 7 __on_dlclose
6: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_finalize
7: 00002070 0 NOTYPE GLOBAL DEFAULT 14 __dso_handle
8: 00001ee0 0 NOTYPE GLOBAL DEFAULT 9 __INIT_ARRAY__
9: 00001ee8 0 NOTYPE GLOBAL DEFAULT 10 __FINI_ARRAY__
10: 000003a1 16 FUNC GLOBAL DEFAULT 7 _Z6func_1v
11: 00002052 20 OBJECT GLOBAL DEFAULT 13 str_3
12: 0000203e 20 OBJECT GLOBAL DEFAULT 13 str_2
13: 00002066 0 NOTYPE GLOBAL DEFAULT ABS _edata
14: 00002066 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
15: 00002080 0 NOTYPE GLOBAL DEFAULT ABS _end
case 2,仍使用LOCAL_STATIC_LIBRARIES宏,libstone_2.cpp的代码修改为:
char hello2[] = "this is a string in libstone_2";
extern char str_2[];
void func_3(){str_2[]+=;}
这个时候readelf的结果是:
readelf -Ws system/lib/libstone_2.so
Symbol table '.dynsym' contains 16 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000037d 20 FUNC GLOBAL DEFAULT 7 _Z6func_3v
2: 0000201f 31 OBJECT GLOBAL DEFAULT 13 hello
3: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_unwind_cpp_pr0
4: 00002000 31 OBJECT GLOBAL DEFAULT 13 hello2
5: 00000390 12 FUNC GLOBAL DEFAULT 7 __on_dlclose
6: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_finalize
7: 00002070 0 NOTYPE GLOBAL DEFAULT 14 __dso_handle
8: 00001ee0 0 NOTYPE GLOBAL DEFAULT 9 __INIT_ARRAY__
9: 00001ee8 0 NOTYPE GLOBAL DEFAULT 10 __FINI_ARRAY__
10: 000003a1 16 FUNC GLOBAL DEFAULT 7 _Z6func_1v
11: 00002052 20 OBJECT GLOBAL DEFAULT 13 str_3
12: 0000203e 20 OBJECT GLOBAL DEFAULT 13 str_2
13: 00002066 0 NOTYPE GLOBAL DEFAULT ABS _edata
14: 00002066 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
15: 00002080 0 NOTYPE GLOBAL DEFAULT ABS _end
可以看到,不仅仅是被引用到的str_2,所有在libstone_1中的global变量都被链接到libstone_2中。
所以可以得到如下的结论:
| 是否链接到调用者模块 | 使用了静态库的global变量 | 不使用 |
| LOCAL_STATIC_LIBRARIES | Y | N |
| LOCAL_WHOLE_STATIC_LIBRARIES | Y | Y |
至于android的编译系统是怎么处理这两个宏的,在./build目录发现其实使用了gcc的参数来区分(in core/definitions.mk ):
1161 -Wl,--whole-archive \
1162 $(call normalize-host-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
1163 -Wl,--no-whole-archive \
1164 $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
综上所述,audio_policy.xxx.so这个policy库使用的是自己的audio_policy_hal.cpp源文件。
原文地址:http://blog.csdn.net/darkengine/article/details/9720131#
LOCAL_WHOLE_STATIC_LIBRARIES与LOCAL_STATIC_LIBRARIES的区别的更多相关文章
- Android.mk高级写法
转:http://blog.csdn.net/langresser_king/article/details/8275291 原本只是想记录一些常用的使用技巧,但是越写越得意(>_<),忍 ...
- Android NDK编程浅入深出之--Android.mk
Android.mk Android.mk是一个向Android NDK构建系统描写叙述NDK项目的GUN Makefile片段.它是每个NDK项目的必备组件. 构建系统希望它出如今jni子文 ...
- Android 显示系统:SurfaceFlinger详解
一.Android系统启动 Android设备从按下开机键到桌面显示画面,大致过程如下图流程: 开机显示桌面.从桌面点击 App 图标到 Activity显示在屏幕上的过程又是怎样的呢?下面介绍And ...
- c#与java的区别
经常有人问这种问题,用了些时间java之后,发现这俩玩意除了一小部分壳子长的还有能稍微凑合上,基本上没什么相似之处,可以说也就是马甲层面上的相似吧,还是比较短的马甲... 一般C#多用于业务系统的开发 ...
- jquery和Js的区别和基础操作
jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...
- 【原】nodejs全局安装和本地安装的区别
来微信支付有2年多了,从2年前的互联网模式转变为O2O模式,主要的场景是跟线下的商户去打交道,不像以往的互联网模式,有产品经理提需求,我们帮忙去解决问题. 转型后是这样的,团队成员更多需要去寻找业务的 ...
- 探究@property申明对象属性时copy与strong的区别
一.问题来源 一直没有搞清楚NSString.NSArray.NSDictionary--属性描述关键字copy和strong的区别,看别人的项目中属性定义有的用copy,有的用strong.自己在开 ...
- X86和X86_64和X64有什么区别?
x86是指intel的开发的一种32位指令集,从386开始时代开始的,一直沿用至今,是一种cisc指令集,所有intel早期的cpu,amd早期的cpu都支持这种指令集,ntel官方文档里面称为&qu ...
- Java中Comparable与Comparator的区别
相同 Comparable和Comparator都是用来实现对象的比较.排序 要想对象比较.排序,都需要实现Comparable或Comparator接口 Comparable和Comparator都 ...
随机推荐
- static为什么一般与final一起用?
static和final的意义是不同的,static修饰的时候代表对象是静态的,而final修饰的时候代表对象只能赋值一次,他们连用的时候是因为定义的那个对象既要它是静态的,也要求它的值不能再被修改. ...
- 如何允许你的应用移动到SD卡?(转至http://blog.csdn.net/feng88724/article/details/6946670)
我们在使用Android手机时发现,有的程序允许被移动到SD卡,而有的不行?这是为什么呢? 因为在Android 2.2版之后, Android应用才被允许移动到SD卡中.而在此之前开发的应用,全部没 ...
- 【苏勇老师Linux 入门笔记】网络基础
IP 地址 IP 编制时一个双层编制方案,一个 IP 地址标示一个主机 (或一个网卡接口). 一个 IP 地址分为两个部分:网络部分(所属区域)和主机部分(标示区域中的哪个主机).IPv4 共32位, ...
- C# 线程池执行操作例子
public partial class Form1 : Form { CountdownEvent hander = ); public static object lock_action = ne ...
- HTML5视频破碎重组特效 强大视觉冲击
HTML5视频播放器很多,但是HTML5视频特效还是很少见的,这款HTML5视频破碎重组特效非常刺激,给人强大的视觉冲击.点击视频任意地方,HTML5将会将这些区域击碎,过一段时间,这些被击碎的视频碎 ...
- Linux服务器 java生成的图片验证码乱码问题
问题:如图所示项目中生成的图形验证码不能正常显示出需要的字体 原因: linux下没有对应的字体 查找项目中使用到系统字体的地方,如下: 解决: 1. 在本地 路径 C:\Windows\Fonts ...
- 8.4 Java 命名规范
Class: 所有单词的首字母大写, TestJava Method: 第一个单词的首字母小写,之后每个单词的首字母大写, getAddressForMe() Property: 第一个单词的首字母小 ...
- 127使用 TableView 自带的单元格样式实现好友列表,另外在单元格中添加辅助按钮
类似的做法如之前这篇随笔:114自定义UITableViewCell(扩展知识:为UITableViewCell添加动画效果) 相比之下:自定义 UITableViewCell 的内容灵活,可根据需求 ...
- C# 异步锁【转】
原文:http://www.yalongyang.com/2013/01/c-sharp-await-lock/ 在C#中,普通用锁很简单 object m_lock = new object(); ...
- Asp.net mvc怎么在razor里写js代码
我试图在Razor里写JS代码,但是不行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 3 ...