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的作用:記錄了程式載入執行期間查詢動態連結庫時的路徑。
靜態庫與動態庫的區別
靜態庫特點總結:
靜態庫對函式庫的連結是放在編譯時期完成的。
程式在執行時與函式庫再無瓜葛,移植方便。
浪費空間和資源,所有相關的目標檔案與牽涉到的函式庫被連結合成一個可執行檔案
動態態庫特點總結:
動態庫把對一些庫函式的連結載入推遲到程式執行的時期。
可以實現程序之間的資源共享。
程序升級變得簡單。(只修改需要升級部分,靜態庫則需要整個重新編譯)