linux的链接库
linux的鏈接庫
- 概述
- 如何指定鏈接的是動態庫還是靜態庫?
- 鏈接庫的順序
- 靜態庫鏈接問題
- gcc鏈接參數
- 庫鏈接參數
- `--whole-archive`
- `--no-whole-archive`
- `--wrap`
- `–start-group` `--end-group`
- ld
- cc
- 動態鏈接庫
- 參考鏈接
概述
程序函數庫可分為3種類型:靜態函數庫(static libraries)、共享函數庫(shared libraries)、動態加載函數庫(dynamically loaded libraries)
程序函數庫可分為下面幾種類型:
- 動態加載函數庫(dynamically loaded libraries),在進程運行期間,使用dlfcn.h中的函數加載、調用、關閉動態庫
注意: LD_LIBRARY_PATH這個也是很關鍵的環境變量,一般的linux系統里都沒設置這個 export LD_LIBRARY_PATH=/usr/local/lib/:/usr/lib/
如何指定鏈接的是動態庫還是靜態庫?
如果我們在gcc中使用參數-l來鏈接某個庫,gcc會首先查找動態庫,動態庫沒有再查找靜態庫,當然我們可以通過-Wl,-Bstatic的方式使用靜態庫,使用完成之后記得加上-Wl,-Bdynamic收尾,否則所有-Wl,-Bstatic之后的庫都變成靜態庫了
在CMake中,如果一個庫既有動態版本,又有靜態版本,可以在CMake里面指定target_link_libraries(xxx.a),指向靜態庫
鏈接庫的順序
GCC在鏈接過程中,對參數中的庫的順序是有要求的,參數右側的庫會先于左側的庫加載,也就是說參數的解析是從右往左的。
假設庫B依賴與庫A,則鏈接的時候要寫為:
gcc -o bin -lB -lA如果寫為:
gcc -o bin -lA -lB則在B中引用的A中的內容就會無法鏈接通過。
靜態庫鏈接問題
靜態庫本質上就是使用ar命令打包一堆.o文件
但是靜態庫和.o文件有不同的地方:
gcc鏈接參數
庫鏈接參數
--whole-archive
調整庫的鏈接順序可以解決大部分問題,但當靜態庫之間存在環形依賴時,則無法通過調整順序來解決。
使用--whole-archive可以告訴編譯器把靜態庫中的所有.o .a都進行鏈接、
--no-whole-archive
- 這個參數是跟在–whole-archive之后,作用是告訴編譯器,后面的庫不需要全部都鏈接了
- 也就是說只有跟在這兩個語句中的參數才會全部被鏈接
--wrap
- C++ 工程實踐(6):單元測試如何 mock 系統調用
-Wl,–wrap -Wl,free
--wrap=symbolUse a wrapper function for symbol. Any undefined reference tosymbol will be resolved to "__wrap_symbol". Any undefinedreference to "__real_symbol" will be resolved to symbol.This can be used to provide a wrapper for a system function. Thewrapper function should be called "__wrap_symbol". If it wishes tocall the system function, it should call "__real_symbol".Here is a trivial example:void *__wrap_malloc (size_t c){printf ("malloc called with %zu/n", c);return __real_malloc (c);}If you link other code with this file using --wrap malloc, then allcalls to "malloc" will call the function "__wrap_malloc" instead.The call to "__real_malloc" in "__wrap_malloc" will call the real"malloc" function.You may wish to provide a "__real_malloc" function as well, so thatlinks without the --wrap option will succeed. If you do this, youshould not put the definition of "__real_malloc" in the same fileas "__wrap_malloc"; if you do, the assembler may resolve the callbefore the linker has a chance to wrap it to "malloc".–start-group --end-group
位于--start-group --end-group中的所有靜態庫將被反復搜索,而不是默認的只搜索一次,直到不再有新的unresolved symbol產生為止。也就是說,出現在這里的.o如果發現有unresolved symbol,則可能回到之前的靜態庫中繼續搜索。
ld
-
ld 命令是二進制工具集 GNU Binutils 的一員,是 GNU 鏈接器,用于將目標文件與庫鏈接為可執行文件或庫文件。相當于編譯里面的鏈接環節
-
gcc里面使用-Wl,開頭的參數都是傳遞給ld的參數,如果直接調用ld,則不需要加-Wl,
常用參數:
cc
在linux下,cc就是gcc,之所以搞了個cc,是為了和unix兼容,cc在unix下是c語言的編譯器
動態鏈接庫
LD_PRELOAD可以作為參數,增加動態鏈接庫的指向,例如:LD_PRELOAD=/data/tools/lib/libzookeeper_mt.so:/data/tools/lib/libprotobuf.so
參考鏈接
總結
- 上一篇: gdb常用命令及参考文档
- 下一篇: raft引入no-op解决了什么问题