最近自己的專案中遇到乙個問題:
編譯乙個動態庫,動態庫中使用了靜態庫的函式如下圖所述
問題來了怎麼編譯最終得到乙個帶有靜態鏈結的動態庫lib***.so?
生成靜態庫lib***1
gcc -o ***1.o -c ***1.c
ar -r ***1.o lib***1.a
生成靜態庫lib***2
gcc -o ***2.o -c ***2.c
ar -r ***2.o lib***2.a
生成靜態庫lib***3
gcc -o ***3.o -c ***3.c
ar -r ***3.o lib***3.a
生成動態庫lib***.so
gcc -o libdynamic.so dynamic.o -shared -fpic -l. -l***1 -l***2 -l***3
gcc報錯:
ib***.a ***.o:relocation against '.rodata' can not be used when ****** a shared object;recomplie with -fpic
gcc -o ***1.o -fpic -shared -c ***1.c
gcc -o ***2.o -fpic -shared -c ***2.c
gcc -o ***3.o -fpic -shared -c ***3.c
之後結合個人除錯和總結看看有沒有其他方法可以解決此類問題(動態庫呼叫靜態庫中的函式)
1,靜態庫被其他程式呼叫,編譯結果為把靜態庫的函式「拷貝」到目標程式中。
明確以上兩個概念之後再來看看實際的情況
****:
void print_papa_said()
#include
#include "dynamic.h"
int main(int argc, char** ar**)
emptyempty
以上**中很清楚的可以看到如下實時。生成乙個動態庫,這個動態庫依中的函式實現依賴於乙個靜態庫。滿足要分析的應用場景。那麼為什麼按照部落格中描述的方法操作gcc,但是結果和我預期的有出入呢?
問題在於兩點:
第一點:使用 -fpic -shared 兩個選項編譯了靜態庫,這個庫還是靜態屬性嗎?假設乙個靜態庫已經被其他軟體和工程廣泛使用了,現在修改了這個靜態庫屬性後是不是會影響其他的軟體?
第二點:為什麼不能編譯出我們預期效果的動態庫?
看看部落格中的操作:
gcc -o static.o -c static.c
ar -r libstatic.a static.o
gcc -o dynamic.o -c dynamic.c
做個靜態庫libstatic.a,然後只編譯dynamic.c不鏈結。
接著使用
gcc -o libdynamic.so -shared -fpic -l. -lstatic dynamic.o
生成乙個名為libdynamic.so動態庫。
一切準備就緒,要用測試軟體測試了
gcc main.c -l. -ldynamic -o main
./libdynamic.so: undefined reference to `print_niuzai_said' collect2: ld returned 1 exit status
鏈結錯誤
我們分析一下原因:
使用命令 nm 檢視可執行程式的符號和函式等
nm libdynamic.so
00001f18 a _dynamic
00001ff4 a _global_offset_table_w _jv_registerclasses
00001f08 d __ctor_end__
00001f04 d __ctor_list__
00001f10 d __dtor_end__
00001f0c d __dtor_list__
00000558 r __frame_end__
00001f14 d __jcr_end__
00001f14 d __jcr_list__
0000200c a __bss_start w __cxa_finalize@@glibc_2.1.3
000004d0 t __do_global_ctors_aux
000003f0 t __do_global_dtors_aux
00002008 d __dso_handle w __gmon_start__
000004a7 t __i686.get_pc_thunk.bx
0000200c a _edata
00002014 a _end
00000508 t _fini
00000388 t _init
0000200c b completed.7021
00002010 b dtor_idx.7023
00000470 t frame_dummy
u print_niuzai_said
000004ac t print_papa_said
u puts@@glibc_2.0
這個u 後面的函式正是靜態庫中想要使用的函式,前面這個u 表示:該符號在當前檔案中是未定義的,即該符號的定義在別的檔案中。
看來這個動態庫名字是對的,但是內容還不全。怎麼辦?修改gcc命令如下:
gcc -o libdynamic1.so -shared -fpic dynamic.o -l. -lstatic
這條命令是告訴gcc先要把dynamic.o這個編譯後未鏈結的檔案中沒有定義的符號鏈結先處理掉,也就是把u開始的函式先鏈結。隨後再把這個未連線的檔案作為動態庫來處理,最後生成乙個動態庫。
有了動態庫libdynamic1.so,再使用nm看看輸出結果:
00001f18 a _dynamic
00001ff4 a _global_offset_table_w _jv_registerclasses
00001f08 d __ctor_end__
00001f04 d __ctor_list__
00001f10 d __dtor_end__
00001f0c d __dtor_list__
000005e4 r __frame_end__
00001f14 d __jcr_end__
00001f14 d __jcr_list__
00002010 a __bss_start w __cxa_finalize@@glibc_2.1.3
00000520 t __do_global_ctors_aux
00000430 t __do_global_dtors_aux
00002008 d __dso_handle w __gmon_start__
000004e7 t __i686.get_pc_thunk.bx
00002010 a _edata
00002018 a _end
00000558 t _fini
000003c8 t _init
00002010 b completed.7021
00002014 b dtor_idx.7023
000004b0 t frame_dummy
00000508 t print_niuzai_said
000004ec t print_papa_said
u puts@@glibc_2.0
0000200c d sz_static
這下這個函式變為 屬性變為t了,t的含義是:該符號位於**區text section。
使用命令:gcc main.c -l. -ldynamic1 -o main
執行main後一切都有了,靜態庫中的函式資訊最後是動態庫中的資訊。
總結:gcc使用的時候帶有引數,這些引數的先後順序直接導致了編譯的結果。特別是在做庫檔案的過程中,有時候看似編譯沒有報錯,但是執行時候就會有問題。這些問題多數出現在鏈結階段。
文中有不足之處請大家指點,謝謝
GCC動態鏈結庫和靜態庫
然後利用ar命令將.o檔案生成靜態庫.a檔案 ar cqs libt3.a tt.o 生成的t3.exe比ttt.exe稍大,但是考慮到ttt.exe還帶了乙個dll,t3就小多了。當然這個比較純屬無聊。另外,生成的.a檔案,改名為.lib檔案也可以,利用vc的cl命令鏈結.a或者.lib都行,都能...
GCC 編譯使用動態鏈結庫和靜態鏈結庫
1 庫的分類 根據鏈結時期的不同,庫又有靜態庫和動態庫之分。靜態庫是在鏈結階段被鏈結的 好像是廢話,但事實就是這樣 所以生成的可執行檔案就不受庫的影響了,即使庫被刪除了,程式依然可以成功執行。有別於靜態庫,動態庫的鏈結是在程式執行的時候被鏈結的。所以,即使程式編譯完,庫仍須保留在系統上,以供程式執行...
GCC 編譯使用動態鏈結庫和靜態鏈結庫
1 庫的分類 根據鏈結時期的不同,庫又有靜態庫和動態庫之分。靜態庫是在鏈結階段被鏈結的 好像是廢話,但事實就是這樣 所以生成的可執行檔案就不受庫的影響了,即使庫被刪除了,程式依然可以成功執行。有別於靜態庫,動態庫的鏈結是在程式執行的時候被鏈結的。所以,即使程式編譯完,庫仍須保留在系統上,以供程式執行...