linux下動態庫編譯的依賴問題

2022-03-25 10:58:19 字數 3403 閱讀 6919

這裡主要是想試驗一下,對乙個具有多層巢狀的動態庫進行編譯時,是否要把最底層的庫也包含進來的問題,結論是:只要直接依賴的庫名稱,不需要最底層庫名稱。

一,目錄結構

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 ...