gcc使用 動態庫鏈結靜態庫

2021-09-24 04:24:50 字數 3977 閱讀 8117

最近自己的專案中遇到乙個問題:

編譯乙個動態庫,動態庫中使用了靜態庫的函式如下圖所述

問題來了怎麼編譯最終得到乙個帶有靜態鏈結的動態庫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 庫的分類 根據鏈結時期的不同,庫又有靜態庫和動態庫之分。靜態庫是在鏈結階段被鏈結的 好像是廢話,但事實就是這樣 所以生成的可執行檔案就不受庫的影響了,即使庫被刪除了,程式依然可以成功執行。有別於靜態庫,動態庫的鏈結是在程式執行的時候被鏈結的。所以,即使程式編譯完,庫仍須保留在系統上,以供程式執行...