linux共享库版本升级
庫原碼:
//舊庫(有綁定指令)
void foo_v1 int f printf "foo_v1\n" ; __asm__ ".symver foo_v1,foo@@VERSION_1.0" ;
//舊庫(無綁定指令)
void foo int f printf "foo_no\n" ; //無綁定指令時,後邊的調用就要和這裡的函數名(foo)一致 //新庫
void foo_v1 int f printf " __asm__ ".symver foo_v1,foo@VERSION_1.0" ;
void foo_v2 int f printf "foo_v2-yuanhao\n" ; __asm__ ".symver foo_v2,foo@@VERSION_1.1" ; //”@@”是指默認函數,必須指定”
說明:舊庫 版本1.0 只有函數foo, 新庫也只有函數foo,只是對foo進行升級,同時實現向前兼容.
編譯舊庫 libfoo.so.1.0 :
libfoo.so.1.0 : foo.c
gcc -shared -fPIC -o libfoo.so.1.0 -Wl,--soname 'libfoo.so' -Wl,--version-script 1.ver foo.c
1.ver內容:
VERSION_1 global: // global 被输出 foo; local: //local 不被输出。它把一些数量的符号限定到本地范围,在共享库的外不可见 *; //如果要升級的函數再local中則會顯示“undefined reference to `foo'”
;
說明: 舊庫編譯後,庫名稱為libfoo.so.1.0, soname名稱為: libfoo.so, export函數foo。
有無綁定指令編譯方式一致。
編譯新庫 libfoo.so.1.1 :
libfoo.so.1.1 : foo.c
gcc -Wall -shared -fPIC -o libfoo.so.1.1 -Wl,--soname 'libfoo.so' -Wl,--version-script 2.ver foo.c
2.ver內容
VERSION_1 global: *;
;
VERSION_2 foo;
VERSION_1;
說明: 新庫編譯後,庫名稱為libfoo.so.1.1, soname名稱為: libfoo.so, export函數foo.
注意:foo所在的類型須一致應同在global或者local。 爲了實現向前兼容應將共享庫soname名設一致。
鏈接舊庫
ln -sf libfoo.so.1.0 libfoo.so
gcc -Wall -o v1 -lfoo -L. -Wl,-rpath . main.c //-lfoo 由於命名規則的約定,-l -libfoo.so。
說明:鏈接后輸出可執行文件為v1(可以在黑色自己設定)。
有無綁定指令,連接方式一致。
鏈接新庫
ln -sf libfoo.so.1.1 libfoo.so
gcc -Wall -o v2 -lfoo -L. -Wl,-rpath . main.c //-lfoo 由於命名規則的約定,-l -libfoo.so。
說明:鏈接后輸出可執行文件為v2(可以在紅色自己設定)。
執行結果
兩庫的main是一樣的:
Main.c
#include
void foo int ;
int main void foo 100 ; return 0; 老版(有無綁定指令一致)結果為:
新版的結果為:
若將老版(有無綁定指令)的可執行文件在新編譯的庫中運行得到的結果是新庫中與其結點一致的那個結果(向前兼容性)。
由於老版中的foo綁定在VERSION_1.0上,所以新庫中須有VERSION_1.0才能運行。
若將新編譯連接好的可執行文件v2移到就庫下運行會因為舊庫中缺少“VERSION_1.1”而無法執行。
備註:
代碼中一些重要的參數
-share此选项将尽量使用动态库,所以生成文件比较小,但是需要系统动态库-fPIC?选项产生位置独立的代码。因为在编译的时候,装入内存的地址还不知道。如果不使用这个选项,库文件可能不会正确运行。-Wl选项告诉编译器将后面的参数传递给链接器。
-soname则指定了动态库的sonamesoname的关键功能是它提供了兼容性的标准:当要升级系统中的一个库时,并且新库的soname和老库的soname一样,用旧库链接生成的程序使用新库依然能正常运行。
-Wl,--version-script mapfile 告诉链接器哪些符号要从生成的共享库中输出出来。
ln -*(選項) 源