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如下

[python] view plaincopy
  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_SRC_FILES := \  
  5.     libstone_1.cpp  
  6.   
  7. LOCAL_MODULE := libstone_1  
  8. LOCAL_MODULE_TAGS := optional  
  9.   
  10. include $(BUILD_STATIC_LIBRARY)  
  11.   
  12. # =========================================  
  13. include $(CLEAR_VARS)  
  14.   
  15. LOCAL_SRC_FILES := \  
  16.     libstone_2.cpp  
  17.   
  18. LOCAL_STATIC_LIBRARIES := libstone_1  
  19. #<span style="color:#ff0000;"> LOCAL_WHOLE_STATIC_LIBRARIES := libstone_1</span>  
  20. LOCAL_MODULE := libstone_2  
  21. LOCAL_MODULE_TAGS := optional  
  22.   
  23. include $(BUILD_SHARED_LIBRARY)  

靜態庫源文件(libstone_1.cpp):

  1. char hello[] = "this is a string in libstone_1";  
  2. char str_2[] = "non static string 1";  
  3. char str_3[] = "non static string 2";  
  4. void func_1(){hello[0]+=1;}  

調用者源文件(libstone_2.cpp):

  1. 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的代碼修改爲:

  1. char hello2[] = "this is a string in libstone_2";  
  2.   
  3. extern char str_2[];  
  4.   
  5. void func_3(){str_2[0]+=1;}  
這個時候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源文件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章