关于编译时链接boost库的困惑

Bev*_*vor 4 compiling libraries dynamic-linking boost

对于客户,我需要向系统添加 boost 1.54。所以我下载了最新版本 (1.55) 并将其构建在一个特殊目录中:/usr/local/lib/boost1.55/。这有效。然后我不得不以这种方式调整 Makefile。

LIBS = $(SUBLIBS) -L/usr/lib/x86_64-linux-gnu -LC:/deps/miniupnpc -lminiupnpc -lqrencode -lrt -LC:/deps/boost/stage/lib -Lc:/deps/db/ build_unix -Lc:/deps/ssl -LC:/deps/libqrencode/.libs -lssl -lcrypto -ldb_cxx -L/usr/local/lib/boost1.55/boost_system-mgw46-mt-sd-1_54 -L/usr /local/lib/boost1.55/boost_filesystem-mgw46-mt-sd-1_54 -L/usr/local/lib/boost1.55/boost_program_options-mgw46-mt-sd-1_54 -L/usr/local/lib/boost1 .55/boost_thread-mgw46-mt-sd-1_54 -lQtDBus -lQtGui -lQtCore -lpthread -lboost_system -lboost_filesystem -lboost_program_options -lboost_thread

在未修改的 Makefile 中,boost 链接如下所示:

-lboost_thread-mgw46-mt-sd-1_54

但这没有用。我无法编译它,因为它没有找到。所以我添加了(如你所见)

-L/usr/local/lib/boost1.55/boost_thread-mgw46-mt-sd-1_54

-lboost_thread

否则它也不会编译。成功编译后,我在二进制文件上执行 ldd 并显示:

libboost_system.so.1.53.0 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.53.0 (0x00007f416c169000) libboost_filesystem.so.1.53.0 => /usr/lib/x86_64-glinux libboost_filesystem.so.1.53.0 (0x00007f416bf52000) libboost_program_options.so.1.53.0 => /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.53.0 (0x00007f416bf52000).libboost_program_options.so.1.53.0 => usr/lib/x86_64-linux-gnu/libboost_thread.so.1.53.0 (0x00007f416bace000)

1.53 是包管理器安装的版本。我不明白为什么它链接到这个版本。如果我没有安装 1.55,它就不会编译,但现在它不会链接到这个版本。对此有什么解释吗?

实际上我的目标是不使用动态链接库,我还没有想出如何做到这一点,但我仍然想知道为什么上述不能按预期工作。

slm*_*slm 6

你没有说这是什么 Linux 发行版,但通常有一个目录,你可以在其中添加动态可链接的库。在 Redhat 发行版(例如 Fedora)上,此目录位于此处,/etc/ld.so.conf.d/.

LD

您可以使用新安装的库的路径将文件添加到此目录,如下所示:

$ cat /etc/ld.so.conf.d/myboost.conf
/usr/local/lib/boost1.55
Run Code Online (Sandbox Code Playgroud)

然后运行这个命令:

$ ldconfig -v
Run Code Online (Sandbox Code Playgroud)

这将处理所有库并重建“缓存”,/etc/ld.so.cache. 这个缓存是什么时,像这样正在指定他们找到库:-lboost_thread-mgw46-mt-sd-1_54

示例输出

$ ldconfig -v
/usr/lib64/atlas:
        libclapack.so.3 -> libclapack.so.3.0
        libptcblas.so.3 -> libptcblas.so.3.0
        libf77blas.so.3 -> libf77blas.so.3.0
        libcblas.so.3 -> libcblas.so.3.0
        liblapack.so.3 -> liblapack.so.3.0
        libptf77blas.so.3 -> libptf77blas.so.3.0
        libatlas.so.3 -> libatlas.so.3.0
/usr/lib64/wxSmithContribItems:
        libwxflatnotebook.so.0 -> libwxflatnotebook.so.0.0.1
...
Run Code Online (Sandbox Code Playgroud)

在向设置添加路径时,我喜欢通过查看此输出来确认,以确保事情按照我期望的方式进行。

LD的缓存

您始终可以使用以下命令打印 .cache 文件的内容:

$ ldconfig -p | head -10
2957 libs found in cache `/etc/ld.so.cache'
    lib3ds-1.so.3 (libc6,x86-64) => /usr/lib64/lib3ds-1.so.3
    libzvbi.so.0 (libc6,x86-64) => /usr/lib64/libzvbi.so.0
    libzvbi-chains.so.0 (libc6,x86-64) => /usr/lib64/libzvbi-chains.so.0
    libzrtpcpp-1.4.so.0 (libc6,x86-64) => /usr/lib64/libzrtpcpp-1.4.so.0
    libzmq.so.1 (libc6,x86-64) => /usr/lib64/libzmq.so.1
    libzmq.so (libc6,x86-64) => /usr/lib64/libzmq.so
    libzipios.so.0 (libc6,x86-64) => /usr/lib64/libzipios.so.0
    libzipios.so (libc6,x86-64) => /usr/lib64/libzipios.so
    libzip.so.1 (libc6,x86-64) => /usr/lib64/libzip.so.1
Run Code Online (Sandbox Code Playgroud)

为什么我的 ldd 输出仍然使用 1.53?

这是因为您的二进制文件正在使用动态库。因此,当编译二进制文件时,它针对的是 1.55 版本的库。但是,当您使用 询问二进制文件时ldd,它位于使用.cache文件内容的环境中。因此,与此二进制文件使用的符号相关联的缓存中的库与 1.53 的符号相匹配,因此您会看到这些库。

您的环境对 1.55 库一无所知,只有您的构建环境,即您的 Makefile,知道这一点。

动态库

将其中的功能视为符号。符号是一个名称,因此这些名称通常不会从库的一个版本更改为另一个版本。因此,如果您要查看诸如 boost 之类的库,则可以使用该工具readelf来获取这些.so文件之一中的符号列表。

例子

$ readelf -Ws /usr/lib64/libboost_date_time-mt.so | head -10

Symbol table '.dynsym' contains 261 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 000000335aa096a8     0 SECTION LOCAL  DEFAULT    9 
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8bad_castD2Ev@GLIBCXX_3.4 (2)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt6locale5_ImplD1Ev@GLIBCXX_3.4 (2)
     4: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND _ZTINSt6locale5facetE@GLIBCXX_3.4 (2)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND wcslen@GLIBC_2.2.5 (3)
     6: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND _ZTISt11logic_error@GLIBCXX_3.4 (2)
Run Code Online (Sandbox Code Playgroud)

在上面的输出中,您可以看到一些FUNC定义,这些名称用于将可执行文件中的函数与某个.so库中的函数“链接”起来。

我过度简化了这个,并且可能稍微解释了一些事情,但我只是试图让你大致了解引擎盖下的机械是如何工作的。

参考