同一系统上的自定义构建和默认增强库

时间:2017-07-19 16:15:54

标签: c++ linux boost shared-libraries

我已经使用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::systemboost::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)。

1 个答案:

答案 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/mytoolmytool如何受此环境变量的影响。