加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux – 说服gcc忽略系统库,转而使用本地安装的库

发布时间:2020-12-13 22:55:15 所属栏目:Linux 来源:网络整理
导读:我正在尝试构建一个使用boost_serialization和boost_iostreams的简单可执行文件. #include fstream#include iostream#include boost/archive/xml_iarchive.hpp#include boost/archive/xml_oarchive.hpp#include boost/iostreams/filtering_stream.hpp#includ
我正在尝试构建一个使用boost_serialization和boost_iostreams的简单可执行文件.

#include <fstream>
#include <iostream>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/device/file.hpp>

int main()
{
    using namespace boost::iostreams;
    filtering_ostream os;
    os.push(boost::iostreams::gzip_compressor());
    os.push(boost::iostreams::file_sink("emptyGzipBug.txt.gz"));
}

不幸的是,我正在使用的系统在/usr/lib /中有一个非常过时的boost_serialization版本,我无法改变它.

当我使用构建示例时,我相当肯定

g++ -o main main.cpp -lboost_serialization -lboost_iostreams

链接器错误的结果是因为gcc使用的是boost_serialization的系统版本,而不是我本地安装的版本.将LIBRARY_PATH和LD_LIBRARY_PATH设置为/ home / andrew / install / lib不起作用.当我建立使用

g++ -o main main.cpp -L/home/andrew/install/lib -lboost_serialization -lboost_iostreams

一切正常.

我的问题是:

>我怎样才能让gcc告诉我它使用的库的文件名?
>是否可以设置环境,以便我不必在gcc的命令行上指定本地boost的绝对路径.

解决方法

PS输入以下信息后,我认为我会善良,并为您的具体案例添加您需要的内容:

g++ -Wl,-rpath,/home/andrew/install/lib -o main main.cpp -I/home/andrew/install/include -L/home/andrew/install/lib -lboost_serialization -lboost_iostreams

gcc本身并不关心库.链接器确实;).
即使链接器需要找到共享库以便它可以解析
符号,它通常不会在可执行文件中存储这些库的路径.

所以,首先,让我们在链接后找出二进制文件中的实际内容:

$readelf -d main | grep 'libboost'
 0x0000000000000001 (NEEDED)             Shared library: [libboost_serialization.so.1.54.0]
 0x0000000000000001 (NEEDED)             Shared library: [libboost_iostreams.so.1.54.0]

只是这样的名字.

实际使用的库由/lib/ld-linux.so.*确定.
在运行时:

$ldd main | grep libboost
        libboost_serialization.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.54.0 (0x00007fd8fa920000)
        libboost_iostreams.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.54.0 (0x00007fd8fa700000)

通过查看/etc/ld.so.cache找到路径(通常是这样
通过运行ldconfig编译).您可以打印其内容:

ldconfig -p | grep libboost_iostreams
    libboost_iostreams.so.1.54.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.54.0
    libboost_iostreams.so.1.49.0 (libc6,x86-64) => /usr/lib/libboost_iostreams.so.1.49.0
    libboost_iostreams.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libboost_iostreams.so

但由于这只是以前查找的缓存结果,
你对以下产量更感兴趣:

$ldconfig -v 2>/dev/null | egrep '^[^[:space:]]|libboost_iostreams'
/lib/i386-linux-gnu:
/usr/lib/i386-linux-gnu:
/usr/local/lib:
/lib/x86_64-linux-gnu:
/usr/lib/x86_64-linux-gnu:
    libboost_iostreams.so.1.54.0 -> libboost_iostreams.so.1.54.0
/lib32:
/usr/lib32:
/lib:
/usr/lib:
    libboost_iostreams.so.1.49.0 -> libboost_iostreams.so.1.49.0

它显示了在查找结果之前查看的路径.
请注意,如果要链接64位程序,它会找到32位
图书馆首先(或反之亦然)然后将被跳过
不相容.否则,使用找到的第一个.

用于搜索的路径在/etc/ld.so.conf中指定
读取(通常在启动时,或安装新的东西后)
以root身份运行ldconfig时.

但是,优先级将路径指定为冒号分隔列表
环境变量LD_LIBRARY_PATH中的路径.
例如,如果我这样做:

$export LD_LIBRARY_PATH=/tmp
$cp /usr/lib/libboost_iostreams.so.1.49.0 /tmp/libboost_iostreams.so.1.54.0
$ldd main | grep libboost_iostreams
    libboost_iostreams.so.1.54.0 => /tmp/libboost_iostreams.so.1.54.0 (0x00007f621add8000)

然后它在/ tmp中找到’libboost_iostreams.so.1.54.0′(即使它是一个libboost_iostreams.so.1.49.0).

请注意,您可以通过传递-rpath来硬编码可执行文件中的路径
链接器:

$unset LD_LIBRARY_PATH
$g++ -Wl,/tmp -o main main.cpp -lboost_serialization -lboost_iostreams
$ldd main | grep libboost_iostreams
    libboost_iostreams.so.1.54.0 => /tmp/libboost_iostreams.so.1.54.0 (0x00007fbd8bcd8000)

这可以使用

$readelf -d main | grep RPATH
 0x000000000000000f (RPATH)              Library rpath: [/tmp]

您可以使用-print-search-dirs命令行选项显示gcc在编译(链接)时使用的搜索路径:

$g++ -print-search-dirs  | grep libraries
libraries: =/usr/lib/gcc/x86_64-linux-gnu/4.7/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/4.7/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/4.7/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/:/lib/x86_64-linux-gnu/4.7/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/4.7/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../:/lib/:/usr/lib/

这可以通过添加-L命令行选项来影响.如果在使用-L选项指定的路径中找不到库,则它会查找通过环境变量GCC_EXEC_PREFIX找到的路径(请参见手册页),如果失败则使用环境变量LIBRARY_PATH.

当您使用-v选项运行g时,它将打印使用的LIBRARY_PATH.

LIBRARY_PATH=/tmp/lib g++ -v -o main main.cpp -lboost_serialization -lboost_iostreams 2>&1 | grep LIBRARY_PATH
LIBRARY_PATH=/tmp/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/tmp/lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../:/lib/:/usr/lib/

最后,请注意,特别是对于提升(但总的来说)你应该使用与正确版本匹配的头文件!所以,如果你的图书馆在运行时链接是版本xyz你应该使用-I命令行选项来获取g来查找相应的头文件,或者事情可能没有链接或更糟,导致无法解释的崩溃.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读