動態(tài)庫編譯詳解

動態(tài)庫編譯詳解:

當(dāng)前類介紹:upper.c ( upper) 依賴于 bottom.c(play)

1.生成一個動態(tài)庫

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -c upper.c bottom.c -I ./include/
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./ -lplay -Wl,-rpath ./,ypa
gcc: error: ./,ypa: 沒有那個文件或目錄
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./ -lplay -Wl,-rpath ./mypath

2.運行程序并且鏈接動態(tài)庫

說明:當(dāng)執(zhí)行可執(zhí)行程序的時候,需要去/lib. /user/lib下和LD_LIBRARY_PATH下尋找so.并不會在當(dāng)前目錄下尋找.

所以執(zhí)行./main.out會報錯.如下:

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
./main.out: error while loading shared libraries: libplay.so: cannot open shared object file: No such file or directory

解決方案:指定.so運行搜尋路徑

1.-Wl,-rpath ./mypath 加入?yún)?shù),并且將libplay.so copy到./mypath目錄下.

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ cp libplay.so ./mypath/
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
Hello, World!
Bottom--->底層的播放功能
Upper---->上層的封裝能力

2.設(shè)置LD_LIBRARY_PATH,指定目錄.

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ cd mypath/ && rm libplay.so 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=./
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
Hello, World!
Bottom--->底層的播放功能
Upper---->上層的封裝能力

說明:指定了-Wl,-rpath, 設(shè)置LD_LIBRARY_PATH也是可以生效的.并不是說只會去-Wl,-rpath下尋找.

3.動態(tài)庫鏈接靜態(tài)庫

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -c upper.c bottom.c -I ./include/  
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ar rcs -o libbottom.a bottom.o

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared  upper.o   -o libplay.so -L ./ -lbottom 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./ -lplay  -I ./include/  -Wl,-rpath ./
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
Hello, World!
Bottom--->底層的播放功能
Upper---->上層的封裝能力

4.動態(tài)庫依賴傳遞的情況

首先生成一個bottom.so,然后用upper.so去依賴bottom.so, 然后main.c 再去依賴upper.so.

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -c *.c -I ./include/ &&rm main.o 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libbottom.so bottom.o 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libplay.so upper.o -L ./ -lbottom 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so 
/usr/bin/ld: warning: libbottom.so, needed by libplay.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: libplay.so: undefined reference to `play'
collect2: error: ld returned 1 exit status
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=./
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
Hello, World!
Bottom--->底層的播放功能
Upper---->上層的封裝能力

說明:這里編譯的時候直接出錯,是因為沒有指定搜尋路徑,所以無法通過編譯.

解決編譯問題方案.

1.我們依然采用LD_LIBRARY_PATH的方式可以解決編譯和運行的問題.

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=./
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
Hello, World!
Bottom--->底層的播放功能
Upper---->上層的封裝能力

2.生成libplay的時候,直接指定-Wl,-rpath 給libbottom.可以解決編譯不通過的問題.

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libplay.so upper.o -L ./  -Wl,-rpath ./  -lbottom  
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ldd libbottom.so 
    linux-vdso.so.1 (0x00007fff45ae3000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd501ef3000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fd502102000)
指定了rpath,在去執(zhí)行./main.out,此時還需要設(shè)置libplay.so 的運行路徑,加入rpath=./
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
./main.out: error while loading shared libraries: libplay.so: cannot open shared object file: No such file or directory
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so  -Wl,-rpath ./
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
Hello, World!
Bottom--->底層的播放功能
Upper---->上層的封裝能力

3.依賴所有庫

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so  libbottom.so
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -c *.c -I ./include/
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libbottom.so bottom.o 
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libplay.so  upper.o   -L ./ -lbottom 
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./   libplay.so  libbottom.so 
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
./main.out: error while loading shared libraries: libplay.so: cannot open shared object file: No such file or directory
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./   libplay.so  libbottom.so  -Wl,-rpath=./
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
./main.out: error while loading shared libraries: libbottom.so: cannot open shared object file: No such file or directory
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=./
yueqingchan@yueqingChan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
Hello, World!
Bottom--->底層的播放功能
Upper---->上層的封裝能力

依賴所有庫只能解決編譯問題,無法處理運行的路徑.

另一種思路:我們在執(zhí)行main.out的時候 執(zhí)行-Wl,-rpath.并不在生成libplay的時候指定,看下是否正常.

yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc -fPIC -shared -o libplay.so upper.o -L ./  libbottom.so 
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so  
/usr/bin/ld: warning: libbottom.so, needed by libplay.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: libplay.so: undefined reference to `play'
collect2: error: ld returned 1 exit status
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -L ./  libplay.so  -Wl,-rpath ./
yueqingchan@yueqingchan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
./main.out: error while loading shared libraries: libbottom.so: cannot open shared object file: No such file or directory

由此可見,-Wl,-rpath 只能針對直接依賴的libplay.so指定了路徑,但是libbottom還是無法查找到 .但是LD_LIBRARY是可以的.

rpath只能對直接依賴的so設(shè)置搜尋目錄,并且可以設(shè)置所有依賴的編譯路徑.

總結(jié): 解決編譯問題,在生成libplay的時候指定-Wl,-rpath運行路徑,或者設(shè)置LD_LIBRARAY_PATH,都可以解決這個問題.

      或者直接依賴所有的.so,但是這樣是不合理的,我們不需要去依賴間接的依賴.

5.動態(tài)庫依賴

當(dāng)我們現(xiàn)在擁有的so包含一個直接依賴的so和很多間接依賴的so,但是沒有設(shè)置rpath.所以是不能直接依賴主so進(jìn)行編譯和運行的.

為了通過編譯:

1.在只鏈接主so的情況下可以去設(shè)置rpath或者LD_LIBRARY_PATH.

2.或者鏈接所有so.

為了通過運行:

為了正常運行可以設(shè)置LD_LIBRARY_PATH.

6.如果我們想只去依賴一個直接so,并且不讓使用方主動去設(shè)置LD_LIBRARY_PATH就可以直接運行程序,還有一種方式:

--disable-new-dtags,--copy-dt-needed-entries

yueqingchan@yueqing-Chan:~/Desktop/TestGcc-Files/TestDynamic1$ export LD_LIBRARY_PATH=
yueqingchan@yueqing-Chan:~/Desktop/TestGcc-Files/TestDynamic1$ gcc main.c -o main.out -Wl,-rpath=./,--disable-new-dtags,--copy-dt-needed-entries -L ./ -lplay
yueqingchan@yueqing-Chan:~/Desktop/TestGcc-Files/TestDynamic1$ ./main.out 
Hello, World!
Bottom--->底層的播放功能
Upper---->上層的封裝能力
yueqingchan@yueqing-Chan:~/Desktop/TestGcc-Files/TestDynamic1$ 

結(jié)論概述:

1.我們在生成間接依賴的庫的時候,為了保證其他庫可以直接依賴,需要加入-Wl,-rpath.保證編譯通過.

2.LD_LIBRARY_PATH可以解決一切編譯運行問題.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末歹垫,一起剝皮案震驚了整個濱河市升酣,隨后出現(xiàn)的幾起案子车吹,更是在濱河造成了極大的恐慌鸠蚪,老刑警劉巖摇庙,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異议泵,居然都是意外死亡熏纯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門着茸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壮锻,“玉大人,你說我怎么就攤上這事涮阔〔滦澹” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵澎语,是天一觀的道長途事。 經(jīng)常有香客問我验懊,道長擅羞,這世上最難降的妖魔是什么尸变? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮减俏,結(jié)果婚禮上召烂,老公的妹妹穿的比我還像新娘。我一直安慰自己娃承,他們只是感情好奏夫,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著历筝,像睡著了一般酗昼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上梳猪,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天麻削,我揣著相機與錄音,去河邊找鬼春弥。 笑死呛哟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匿沛。 我是一名探鬼主播扫责,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼逃呼!你這毒婦竟也來了鳖孤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤抡笼,失蹤者是張志新(化名)和其女友劉穎苏揣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔫缸,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡腿准,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拾碌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吐葱。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖校翔,靈堂內(nèi)的尸體忽然破棺而出弟跑,到底是詐尸還是另有隱情,我是刑警寧澤防症,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布孟辑,位于F島的核電站哎甲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏饲嗽。R本人自食惡果不足惜炭玫,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望貌虾。 院中可真熱鬧吞加,春花似錦、人聲如沸尽狠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽袄膏。三九已至践图,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沉馆,已是汗流浹背码党。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留悍及,地道東北人闽瓢。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像心赶,于是被迫代替她去往敵國和親扣讼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容