這裡主要是想試驗一下,對乙個具有多層巢狀的動態庫進行編譯時,是否要把最底層的庫也包含進來的問題,結論是:只要直接依賴的庫名稱,不需要最底層庫名稱。
一,目錄結構
zzz├── add
│ ├── add.cpp
│ └── add.h
├── calc
│ ├── calc.cpp
│ └── calc.h
├── main
├── main.cpp
├── pkg
│ ├── pkg.cpp
│ └── pkg.h
└── sub
├── sub.cpp
└── sub.h
二,檔案內容:
1, add模組內容:
[add.cpp ]
int add(int a, int b)
[add.h]
extern int add(int a, int b);
2, sub模組內容:
[sub.cpp]
int sub(int a, int b)
[sub.h]
extern int sub(int a, int b);
3, calc模組內容:
[calc.cpp]
#include "calc.h"
#include "add.h"
#include "sub.h"
#include
void func(int a, int b)
[calc.h]
extern void func(int a, int b);
4, pkg模組: 對calc模組進行了簡單封裝
[pkg.cpp]
#include "pkg.h"
#include "calc.h"
void pkg_func()
[pkg.h]
extern void pkg_func();
5, main程式:呼叫pkg模組
[main.cpp]
#include "pkg.h"
int main()
三,編譯:
zzz目錄下:(單功能模組)
1,[add模組]
g++ -g -shared -fpic add/add.* -o libadd.so
2, [sub模組]:(單功能模組)
g++ -g -shared -fpic sub/sub.* -o libsub.so
3, [calc模組]: clac模組依賴於add和sub模組,用到了兩者的標頭檔案,並呼叫了介面
錯誤:g++ -g -shared -fpic -iadd -isub calc/calc.* -o libcalc.so
(編譯雖然可以過,但是引數不足,這種遺漏依賴庫的問題現在不解決,在編譯巢狀它的上層庫時就會暴露出來)
正確:g++ -g -shared -fpic -iadd -isub -ladd -lsub -l. calc/calc.* -o libcalc.so
4, [pkg模組]:封裝calc模組
錯誤:g++ -g -shared -fpic -icalc pkg/pkg.* -o libpkg.so
正確:g++ -g -shared -fpic -icalc -lcalc -l. pkg/pkg.* -o libpkg.so
5, [main程式]
g++ -g -ipkg -lpkg -l. main.cpp -o main
四,試驗
我們知道各模組的依賴關係:pkg->calc->add+sub,讓我們慢慢分析,通過3,4步的編譯引數我們可以看出:
編譯鏈結某個so的時候,系統並不檢查介面是否可以匯出,而只是檢查編譯是否通過。所以編譯引數只包含依賴庫的檔名是可以通過,但並不保證是正確的。(製作動態庫的時候,到底有沒有鏈結這個過程?,否則為什麼在第一層呼叫庫的時候就不報錯呢)
1)g++ -g -ipkg main.cpp -o main
/tmp/ccjkiuei.o: in function `main':
/home/test/zzz/main.cpp:5: undefined reference to `pkg_func()'
a: main.cpp裡面沒有找到pkg_func介面,沒包含庫名稱怎麼可能找得到介面呢?
2) g++ -g -ipkg -lpkg main.cpp -o main
/usr/bin/ld: cannot find -lpkg
collect2: ld 返回 1
a: 沒有找到庫名,需要指定庫目錄
3)g++ -g -ipkg -lpkg -l. main.cpp -o main
/tmp/cc4jknbm.o: in function `main':
/home/test/zzz/main.cpp:5: undefined reference to `pkg_func()'
./libpkg.so: undefined reference to `func(int, int)'
collect2: ld 返回 1
a: libpkg.so裡沒有找到func介面,說明libpkg.so庫在編譯時沒有包含依賴庫名稱,執行第4步的正確編譯命令。
4)g++ -g -ipkg -lpkg -l. main.cpp -o main
/tmp/ccgpm3hq.o: in function `main':
/home/test/zzz/main.cpp:5: undefined reference to `pkg_func()'
libcalc.so: undefined reference to `sub(int, int)'
libcalc.so: undefined reference to `add(int, int)'
collect2: ld 返回 1
a: libcalc.so裡沒找到add,sub介面,說明libcalc.so時在編譯時沒有包含依賴庫名稱,執行第3步正確編譯命令。
5) g++ -g -ipkg -lpkg -l. main.cpp -o main
100+80=180
100-80=20
五,引申:
現在要在main.cpp是需跨層呼叫add模組的add介面,需要做的操作是:
1)新增**:main.cpp包含add.h標頭檔案,增加add()函式**,
2)新增編譯選項:只需要新增-i選項即可,不需要再加-l選項的。
六,結論:
因為庫具有疊加性,最上層庫的介面中已經包含了中間層和最低層的匯出介面了,這個可以使用ldd命令來檢視。
所以在編譯具有多層依賴的動態庫時,你只需要包含當前庫直接依賴的庫名稱即可,不需要再把它所依賴庫的依賴庫名稱包含進來。以上面的例子來說,編譯pkg模組庫的時候,只需要把calc的庫包含進來就行了。
linux 下 奇怪的 動態庫 依賴問題
總結如下 1 當你在編譯生成靜態庫的時候,只需要相應的依賴庫庫的標頭檔案即可.只有在你想生成so,或可執行檔案 時,才需要lib庫.對於你沒有用到的lib,但是不包含又編譯失敗,那麼只包含其標頭檔案即可.2 如果你同時使用了多個庫,而庫之間又相互依賴,那麼在鏈結是,把最底層的依賴庫放在最右側.否則可...
linux下動態庫的編譯使用
linux下動態庫的編譯 1 實踐 test cl.c 1 include 2 include 3 4 extern int add int a,int b 5 define labeladdr 6 main 7 test so.c 1 int add int a,int b 2 test so1....
Linux 檢視動態庫依賴
檢視動態庫依賴3種方法 1 ldd bin grep linux gate.so.1 0xffffe000 libc.so.6 lib libc.so.6 0xb7eca000 lib ld linux.so.2 0xb801e000 2 ld trace loaded objects 1 bin ...