2016-04-01 280 views
0

由於我使用的是一些較老的第三方代碼,我編譯了boost::systemboost::serialization與舊的GCC ABI(https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html)。衝突的升級版本

,我把它們內置到已被設置爲鏈接的有效路徑/usr/local/lib(我用到其他庫有作爲),並將其重命名爲:

$ ls /usr/local/lib/libboost_* 

/usr/local/lib/libboost_serialization_old_abi.so 
/usr/local/lib/libboost_serialization_old_abi.so.1.60.0 
/usr/local/lib/libboost_system_old_abi.so 
/usr/local/lib/libboost_system_old_abi.so.1.60.0 
/usr/local/lib/libboost_wserialization_old_abi.so 
/usr/local/lib/libboost_wserialization_old_abi.so.1.60.0 

默認,主流Boost庫正在像往常一樣的/usr/lib。會發生什麼事是,當我任何一段代碼鏈接到這些特定的庫與自定義標記-lboost_system_old_abi-lboost_serialization_old_abi,生成的二進制文件將被鏈接到默認Boost庫

$ ldd darwin_socket 

linux-vdso.so.1 (0x00007ffd137ea000) 
/usr/local/webots/resources/projects/robots/darwin-op/libraries/darwin/libdarwin.so (0x00007fcb9edaa000) 
libipsocket.so.1 => /usr/local/lib/libipsocket.so.1 (0x00007fcb9eb7b000) 
libboost_system.so.1.60.0 => /usr/lib/libboost_system.so.1.60.0 (0x00007fcb9e977000) 
libboost_serialization.so.1.60.0 => /usr/lib/libboost_serialization.so.1.60.0 (0x00007fcb9e739000) 
libController.so => not found 
libCppController.so => not found 
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fcb9e3b7000) 
libm.so.6 => /usr/lib/libm.so.6 (0x00007fcb9e0b2000) 
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fcb9de9c000) 
libc.so.6 => /usr/lib/libc.so.6 (0x00007fcb9dafb000) 
/lib64/ld-linux-x86-64.so.2 (0x00007fcb9efc1000) 
librt.so.1 => /usr/lib/librt.so.1 (0x00007fcb9d8f3000) 
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fcb9d6d6000) 

這是很奇怪的,因爲如果使用原始的-lboost_system-lboost_serialization標誌,由於新舊ABI不兼容,gcc甚至無法鏈接到默認提升。

那麼究竟發生了什麼?

回答

1

問題是,只是重命名自定義構建的庫是不夠的。庫名稱嵌入到庫中,作爲soname(您可以使用readelf -d命令查看它),並在您的應用程序被庫所喜歡時使用。基本上,自定義庫中的sonames將作爲依賴項放到應用程序二進制文件中,因爲它們與官方Boost庫名稱相同,所以錯誤的二進制文件會在運行時加載。

您必須確保在構建過程中正確命名了構建的Boost庫。您可以嘗試在您的b2命令行中添加--buildid=old_abi選項。