C++靜態庫和動態庫
靜態庫與動態庫
首先簡單介紹一下gcc 指令
ubuntu 下安裝gcc g++ 方法
sudo apt install gcc g++
gcc 的簡單使用
建立hello.c 源文件
gcc hello.c => 生成a.out
gcc hello.c -o hello => 生成hello
./a.out | ./hello 運行
編譯步驟
- 預處理 生成.i 文件
- 編譯 生成.s 文件
- 生成目標文件 .o
- 鏈接各個.o 文件生成可執行文件
gcc常用參數選項
gcc編譯選項 | 選項的意義 |
---|---|
-E | 預處理指定的源文件,不進行編譯 |
-S | 編譯指定的源文件,不進行彙編 |
-c | 編譯、彙編指定的源文件,不進行鏈接 |
-o | 指定生成文件名字 |
-I directory | 指定 include 包含文件的搜索目錄 |
-g | 編譯時,生成調試信息,該程序可以被調試器調試 |
-D | 在程序編譯的時候,指定一個宏 如打開DEBUG -D DEBUG |
-w | 不生成任何警告信息 |
-Wall | 生成所有警告信息 |
-O [123] | n的取值範圍:0~3。編譯器的優化選項的4個級別,-O0表示沒有優化,-O1為缺省值,-O3優化級別最高 |
-l | 在程序編譯的時候,指定使用的庫 |
-L | 指定編譯的時候,搜索的庫的路徑。 |
-fPIC/fpic | 生成與位置無關的代碼 |
-shared | 生成共享目標文件。通常用在建立共享庫時 |
-std | 指定編譯標準 如-std=c++1z或-std=gnu++17或-std=c++17 |
靜態庫
- Linux 靜態庫
- libxxx.a
- lib 前綴
- xxx 庫的名字
- .a 後綴
- libxxx.a
- Windows 靜態庫
- libxxx.lib
靜態庫的製作
- 生成 .o 文件
gcc xxx.c xxx.c xxx.c -c
- 使用ar 打包
- ar rcs
- -r 替換
- -c 創建
- -s 索引
ar rcs libxxx.a xxx.o xxx.o xxx.o
靜態庫的使用
引入頭文件與需要的靜態庫libxxx.a (頭文件中聲明了靜態庫的接口,libxxx.a為接口的實現)
gcc main.c -o app -I ./include/ -L 靜態庫路徑 -l 靜態庫名字
- -L 靜態庫路徑
- -l 靜態庫名字 為libxxx.a 中的xxx
動態庫/共享庫
- Linux 動態庫
- libxxx.so
- lib 前綴
- xxx 庫的名字
- .so 後綴
- libxxx.so
- Windows 動態庫
- libxxx.dll
動態庫製作
- 生成 .o 文件 (與位置無關)
gcc -c xxx.c xxx.c xxx.c -c -fpic
-fpic/-fPIC 使用相對地址記錄代碼位置 - gcc -shared xxx.o xxx.o xxx.o -o libcxxx.so
動態庫使用
引入頭文件與需要的動態庫libxxx.so 頭文件中聲明了靜態庫的接口,libxxx.a為接口的實現)
$ gcc main.c -o app -I ./include/ -L 動態庫路徑 -l 動態庫名字
工作原理
- 靜態庫在程序編譯時會鏈接到目標代碼中,程序運行時不再需要靜態庫,體積較大。每次編譯都需要載入靜態代碼,內存開銷大。
- 動態庫在程序運行時才被載入,程序運行時需要動態庫存在,體積較小。系統只需載入一次動態庫,不同程序可以得到內存中相同的動態副本,內存開銷小。
解決動態庫找不到的問題:
第一種: 將動態庫的絕對路徑添加到 LD_LIBRARY_PATH 中
- 測試時候使用的, 終端關閉, 設置失效:
在當前終端中執行: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/庫的路徑 - 長久設置, 將export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/庫的路徑 寫到配置文件中
- 用戶: ~/.bashrc
添加: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/庫的路徑
- 系統: /etc/profile
添加: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/庫的路徑
- 添加完成執行命令, 使修改生效:
. ~/.bashrc
. /etc/profile
source /etc/profile
. 相當於 source
第二種: 在 /etc/ld.so.cache 添加動態庫路徑
- 打開文件: /etc/ld.so.conf
- 將.so文件路徑的目錄添加到/etc/ld.so.conf, 更新: sudo ldconfig
- /etc/ld.so.conf的作用:記錄了程序加載運行期間查找動態鏈接庫時的路徑。
靜態庫與動態庫的區別
靜態庫特點總結:
靜態庫對函數庫的鏈接是放在編譯時期完成的。
程序在運行時與函數庫再無瓜葛,移植方便。
浪費空間和資源,所有相關的目標文件與牽涉到的函數庫被鏈接合成一個可執行文件
動態態庫特點總結:
動態庫把對一些庫函數的鏈接載入推遲到程序運行的時期。
可以實現進程之間的資源共享。
程序升級變得簡單。(只修改需要升級部分,靜態庫則需要整個重新編譯)