我已经使用system
宏(https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html)构建了一些增强库(特别是serialization
和_GLIBCXX_USE_CXX11_ABI=0
),因为我实际上是这样的。{使用boost::asio
在我的代码和旧应用程序之间共享信息(通过平均值)(Webots 7.4.3,pre GCC-5)。但是,我已经在我的系统中安装了标准的boost库(其他几个应用程序需要)。我已选择将自定义编译版本安装到/usr/local/lib
(默认版本保存在/usr/lib
中),并使用后缀_oldabi
重命名库:
$ ls -lash /usr/local/lib | grep boost
1,1M -rw-r--r-- 1 root root 1,1M jun 21 14:17 libboost_serialization_oldabi.a
416K -rw-r--r-- 2 root root 415K jun 21 14:17 libboost_serialization_oldabi.so
416K -rw-r--r-- 2 root root 415K jun 21 14:17 libboost_serialization_oldabi.so.1.64.0
0 lrwxrwxrwx 1 root root 39 jun 21 14:18 libboost_serialization.so.1.64.0 -> libboost_serialization_oldabi.so.1.64.0
48K -rw-r--r-- 1 root root 46K jun 21 14:17 libboost_system_oldabi.a
20K -rw-r--r-- 2 root root 20K jun 21 14:17 libboost_system_oldabi.so
20K -rw-r--r-- 2 root root 20K jun 21 14:17 libboost_system_oldabi.so.1.64.0
0 lrwxrwxrwx 1 root root 32 jun 21 14:18 libboost_system.so.1.64.0 -> libboost_system_oldabi.so.1.64.0
708K -rw-r--r-- 1 root root 706K jun 21 14:17 libboost_wserialization_oldabi.a
300K -rw-r--r-- 2 root root 299K jun 21 14:17 libboost_wserialization_oldabi.so
300K -rw-r--r-- 2 root root 299K jun 21 14:17 libboost_wserialization_oldabi.so.1.64.0
0 lrwxrwxrwx 1 root root 40 jun 21 14:18 libboost_wserialization.so.1.64.0 -> libboost_wserialization_oldabi.so.1.64.0
代码运行良好,套接字通信按预期工作。但是,当尝试在没有安装默认boost库的情况下在另一台计算机上设置代码时(仅boost::system
和boost::serialization
的自定义编译版本),执行写入/读取时我得到(system:9) Bad file descriptor
操作。在试图找出问题的同时,我回到了原来的计算机,并查看/proc/XXXX/maps
我注意到我的可执行文件实际上是在运行时在/usr/lib
下加载默认的boost库,尽管它与编译时定制的版本。
因此,我的问题是1)如何使系统优先/usr/local/lib
优先于/usr/lib
或强制它将_boost_oldabi
后缀标识为不同的库; 2)弄清楚为什么添加GCC ABI宏似乎打破了代码;源代码,make文件和库完全相同,计算机之间唯一不同的是OS(Arch Linux和Ubuntu)。
答案 0 :(得分:1)
序言:如果您只需要为单个工具提供自定义boost库,最好将它们安装到特定于此单个工具的位置。将自定义库安装到系统范围的位置(/usr/local/lib
)不是一个好主意,因为
/usr/local/lib
,你就无法知道在那里使用libs的内容。如果你只为你的软件提供它们会更好。例如,如果您的软件位于/srv/niceproject/bin
,那么这些库可以存在于/srv/niceproject/lib
中。
请注意,Linux中的共享库处理非常智能,可以处理具有不同版本的库,所有二进制文件都将根据所需的版本映射到库中。但是,它取决于链接器插入二进制文件的特殊符号。如果仅更改编译器标志,则这些符号可能相同,因此可以链接false lib。
您可以通过更改/usr/local/lib
和/etc/ld.so.conf
中的共享库顺序,然后调用/etc/ld.so.conf.d
来确定ldconfig
的优先级。要获取当前可见库的列表,请使用ldconfig -p
。
有很多,所以ldconfig -p|grep libboost
可能会有更好的结果。
共享库目录顺序也受LD_LIBRARY_PATH
环境变量的影响,可以为每个进程指定什么。因此,使用
LD_LIBRARY_PATH=/srv/niceproject/lib /srv/niceproject/bin/mytool
将在某种程度上调用mytool
,它首先尝试在/srv/niceproject/lib
中找到库,然后在它之后查看系统范围内的库。它是一个以冒号分隔的pathes列表,如$PATH
。
将二进制文件与绝对路径给定的库链接将硬编码到库中的绝对路径。所以:
gcc -o mytool -l/usr/local/lib/libboost_oldapi_anything.so
此外,这通常是一个肮脏的解决方案,但它可以解决您的问题。
您可以使用ldd
工具查看实际库加载的内容:
# ldd /bin/bash
linux-vdso.so.1 => (0x00007ffd1c1cf000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f4baa499000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4baa295000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4ba9eca000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4baa6d0000)
ldd
是一个特殊的二进制文件,您可以指定任何LD_LIBRARY_PATH
,它不会影响它(但它会影响您使用它检查的二进制文件)。在我的示例中,将显示LD_LIBRARY_PATH=/srv/niceproject/lib ldd /srv/niceproject/bin/mytool
,mytool
如何受此环境变量的影响。