http://blog.csdn.net/huqinwei987/article/details/50517780
背景:效率考慮,要重用把服務器主備機方案,以庫Libmdpha(高可用)的形式加進主工程dds(調度數據服務器)。
有源代碼,打算直接編譯Libmdpha.so.xxx,加入主工程dds。復制動態庫libmdpha.so.xxx到主工程相關路徑,並改makefile,makefile中主要加復制命令和建立軟連接的命令,庫名注意統一:
引用庫中加入Libmdpha
同時加
cp -f $(INTERFACES_PATH)/libmdpha/$(VER_libmdpha)/lib/libmdpha.so.$(VER_libmdpha).$(VER_libmdpha_SUB) ../lib/
ln -sf ../lib/libmdpha.so.$(VER_libmdpha).$(VER_libmdpha_SUB) ../lib/libmdpha.so
將Libmdpha庫放在dds主工程中,建立動態鏈接。
WARNING
憑回憶寫,懶得復現了過於繁瑣,比如剛加入主工程時編譯的WARNING,好像是libmdpha中的so.2和so.3之類的,在主工程沒有,所以WARNING找不到那些動態庫別名。
然后就是在主工程中做那些相應的別名。
本着負責的原則,重現了下,路徑不對的后果如下,需要同級的lib下,其實在主工程中庫全在同級路徑
會碰到兩個工程的路徑設置兼容問題
在Libmdpha的makefile指定了libmdpha.so依賴的庫和路徑../lib
但是在dds主工程中,卻是同級關系,所以兩個編譯腳本和路徑設置必須有個妥協,所以把Libmdpha的依賴庫路徑改了,源與目的在一起,看起來亂一點,這樣倒是不用主工程dds以及dds依賴的更多的庫了。
看似工作完成了。
但是。。。
但是,Libmdpha和dds7600工程依賴了相同的底層庫(log庫、工具庫、初始化庫等),版本卻不一樣(因為他們開發高可用庫的時候用的是那個時候的庫,現在dds用的新版本的庫)。
有兩種解決思路:
第一種方案:
庫文件全復制進去,主工程dds和主備庫Libmdpha各連接各的,xxx.so指向dds依賴的新版底層庫,xxx.so.1指向libmdpha依賴的舊版底層庫。互不干擾,缺點是兩個版本的底層庫都復制進去,臃腫,而且也混亂,長此以往,越來越亂,別人也會看不懂關聯這么多怎么回事。
第二種方案:
把libmdpha換了依賴庫(和dds統一),重新編譯,好在有源代碼。
隱患是可能會錯,畢竟底層庫版本不同了,但願接口沒區別。
用了第二種方案:把和主工程同版本的底層庫放進去編譯,然后再把libmdpha往主工程里放,然后用個和庫libmdpha的makefile設置相同的別名*.so.3或者*.so.2,而主工程原來依賴的別名為*.so,因為已經統一了版本,其實是同一個文件。
最后,編譯成功。
但是仔細看仍然有問題
#ldd
可以看到
libmdpha庫依賴的這四個庫其實鏈空了,雖然編譯成功了,但是動態庫缺失可能會導致程序運行失敗。
解決方法是繼續改libmdpha庫的makefile,加上rpath:
左圖是主工程的參考,右圖是未加rpath的libmdpha庫。
加后
LFLAGS = -w -shared -Wl,-soname,$(SO_NAME),-rpath=../lib
或
LFLAGS = -w -shared -Wl,-soname,$(SO_NAME),-rpath,../lib
在GNU環境下,有-Wl后,逗號和等號可以起到類似作用。